ElasticSearch 更新 child 文档未更新 parent 文档

ElasticSearch update to child document not updating parent document

ElasticSearch 中有没有一种方法可以在 child 文档的属性发生更改时自动更新所有 parent 文档?也许我正在跟踪我是如何使用 ElasticSearch 的。代码:

        var child = new Child
        {
            Id = Guid.NewGuid(),
            Name = "Child"
        };

        var parent = new Parent
        {
            Id = Guid.NewGuid(),
            Name = "Parent",
            Child = child
        };

        var nestedResponse = client.CreateIndex("index", i => i
            .Mappings(m => m
                .Map<Parent>(map => map
                    .AutoMap()
                    .Properties(ps => ps
                        .Nested<Child>(n => n
                            .Name(p => p.Child)
                            .AutoMap()
                        )
                    )
                )
            )
        );

        var indexResult = client.Index<Parent>(parent);
        indexResult = client.Index<Child>(child);

        var reloadedParent = client.Get<Parent>(parent.Id.ToString()).Source;
        var childName = reloadedParent.Child.Name;
        child.Name = "child changed";
        var updateRequest = new UpdateRequest<Child, Child>("index", typeof(Child), child.Id);
        updateRequest.Doc = child;

        var reindexResult = client.Update<Child>(updateRequest);

        var reloadedParentAfterChildChange = client.Get<Parent>(parent.Id.ToString()).Source;
        var childChangedName = reloadedParentAfterChildChange.Child.Name;

        Assert.AreEqual(child.Name, childChangedName);

    }
}

public class Parent
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public Child Child { get; set; }
}

public class Child
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

Child可以属于很多不同的Parents。有什么方法可以将对 Child 的更改传播到包含 Child 的所有 Parents?我正在使用来自 c# 的 Nest 客户端。

你的做法不太对。

  1. 在映射中,您将 Child 属性 设置为嵌套类型,然后索引 parentchild

    嵌套类型在其 嵌套 的类型上建立索引,即 json 表示 Child 属性在 parent 上被索引为 parent json 文档的一部分。

    在 Elasticsearch 中可以有一个 Parent/Child relationship 和一个 parent 到许多 children,这听起来你需要反转 Parent/Child 角色在您的模型中使用。

  2. 建立索引后,您将获得 parent 文档的来源,更改 parent 上 child 的 child 名称,但是然后更新您已编制索引的 child 文档, 没有 更新 parent child.

    许多文档可以具有相同的嵌套文档值,但这些文档之间没有任何关系,因此更新值需要更新每个文档。这可以通过 Update By Query API 来完成。

这里有一个例子来演示;在生产中,您可能不想禁用直接流式传输、注销所有 request/responses、在每次操作后调用刷新等

void Main()
{
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    var defaultIndex = "default-index";
    var connectionSettings = new ConnectionSettings(pool)
            .DefaultIndex(defaultIndex)
            .PrettyJson()
            .DisableDirectStreaming()
            .OnRequestCompleted(response =>
                {
                    // log out the request
                    if (response.RequestBodyInBytes != null)
                    {
                        Console.WriteLine(
                            $"{response.HttpMethod} {response.Uri} \n" +
                            $"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}");
                    }
                    else
                    {
                        Console.WriteLine($"{response.HttpMethod} {response.Uri}");
                    }

                    Console.WriteLine();

                    // log out the response
                    if (response.ResponseBodyInBytes != null)
                    {
                        Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
                                 $"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" +
                                 $"{new string('-', 30)}\n");
                    }
                    else
                    {
                        Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
                                 $"{new string('-', 30)}\n");
                    }
                });

    var client = new ElasticClient(connectionSettings);

    if (client.IndexExists(defaultIndex).Exists)
        client.DeleteIndex(defaultIndex);

    var child = new Child
    {
        Id = Guid.NewGuid(),
        Name = "Child"
    };

    var parent = new Parent
    {
        Id = Guid.NewGuid(),
        Name = "Parent",
        Child = child
    };

    var anotherParent = new Parent
    {
        Id = Guid.NewGuid(),
        Name = "Another Parent",
        Child = child
    };

    var nestedResponse = client.CreateIndex(defaultIndex, i => i
        .Mappings(m => m
            .Map<Parent>(map => map
                .AutoMap()
                .Properties(ps => ps
                    .String(s => s
                        .Name(nn => nn.Id)
                        .NotAnalyzed()
                    )
                    .Nested<Child>(n => n
                        .Name(p => p.Child)
                        .AutoMap()
                        .Properties(p => p
                            .String(s => s
                                .Name(nn => nn.Id)
                                .NotAnalyzed()
                            )
                        )
                    )
                )
            )
        )
    );

    var indexResult = client.Index<Parent>(parent);
    indexResult = client.Index<Parent>(anotherParent);

    var fetchedParent = client.Get<Parent>(parent.Id).Source;
    var fetchedAnotherParent = client.Get<Parent>(anotherParent.Id).Source;

    client.Refresh(defaultIndex);

    var update = client.UpdateByQuery<Parent>(u => u
        .Query(q => q
            .Nested(n => n
                .Path(p => p.Child)
                .Query(qq => qq
                    .Term(t => t.Child.Id, child.Id)
                )
            )
        )
        .Script("ctx._source.child.name='New Child Name'")
        .Conflicts(Conflicts.Abort)
        .WaitForCompletion()
        .Refresh()
    );

    fetchedParent = client.Get<Parent>(parent.Id).Source;
    fetchedAnotherParent = client.Get<Parent>(anotherParent.Id).Source;
}


public class Parent
{
    public Guid Id { get; set; }

    public string Name { get; set; }

    public Child Child { get; set;} 
}

public class Child
{
    public Guid Id { get; set; }

    public string Name { get; set; } 
}