当子文档的属性发生变化时,ElasticSearch中是否有一种方法可以自动更新所有父文档?也许我正在追踪我如何使用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; }
}
孩子可以属于许多不同的父母。是否有任何方法可以将对儿童的更改传播给包含儿童的所有父母?我正在使用c#的Nest客户端。
答案 0 :(得分:1)
你做的不太对劲。
在映射中,您将Child
属性设置为嵌套类型,但随后将parent
和child
都编入索引。
嵌套类型在嵌套的类型上建立索引,也就是说,表示Child
上的parent
属性的json被索引为父级的一部分json文件。
Elasticsearch中可能有一个Parent/Child relationship,其中包含许多子项的父项,这听起来像您需要在模型中反转父/子角色才能使用。
在建立索引之后,您将获得parent
文档的来源,更改父级的子级名称,但随后更新已编入索引的子文档,不带使用孩子更新parent
。
许多文档可以具有相同的嵌套文档值,但这些文档之间没有关系,因此更新值需要对每个文档进行更新。这可以使用Update By Query API来完成。
这是示例来演示;在生产中,您可能不想禁用直接流式传输,注销所有请求/响应,每次操作后调用刷新等等。
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; }
}