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 客户端。
你的做法不太对。
在映射中,您将 Child
属性 设置为嵌套类型,然后索引 parent
和 child
。
嵌套类型在其 嵌套 的类型上建立索引,即 json 表示 Child
属性在 parent
上被索引为 parent json 文档的一部分。
在 Elasticsearch 中可以有一个 Parent/Child relationship 和一个 parent 到许多 children,这听起来你需要反转 Parent/Child 角色在您的模型中使用。
建立索引后,您将获得 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; }
}
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 客户端。
你的做法不太对。
在映射中,您将
Child
属性 设置为嵌套类型,然后索引parent
和child
。嵌套类型在其 嵌套 的类型上建立索引,即 json 表示
Child
属性在parent
上被索引为 parent json 文档的一部分。在 Elasticsearch 中可以有一个 Parent/Child relationship 和一个 parent 到许多 children,这听起来你需要反转 Parent/Child 角色在您的模型中使用。
建立索引后,您将获得
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; }
}