且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

嵌套对象的弹性搜索版本2.0.0.0部分更新

更新时间:2023-02-08 23:23:44

因为 NodeList 是一个列表< Node> ,不可能进行部分更新,因为提供的值将取代现有值。



使用乐观并发控制


  1. 获取现有文档

  2. 在应用程序中进行更改

  3. 将更改的文档索引到Elasticsearch,使用获取请求中的版本号进行乐观并发

以下内容将会起作用。

  var getResponse = client。得到&LT;格拉夫&GT( 图形-ID); 

var graph = getResponse.Source;
var node = graph.NodeList.First(n => n.Id ==node-id);

//更改节点
node.Name =new name;
node.EdgeList.First()。Cost = 9.99;

var indexResponse = client.Index(graph,i => i
//指定获取请求的版本
.Version(getResponse.Version)
);

如果 Graph 之间的更改get和索引调用,然后在索引调用中返回409响应。



如果您经常需要更新 Node s和 Edge s彼此独立,您可以决定用父/子关系,这将允许您更新,而不需要拉回对象图并对更改进行索引。 >

Say, I have some POCO like following.

public class Graph
{
    public string Id { get; set; } // Indexed by this
    public List<Node> NodeList { get; set; }
}

public class Node
{
    public string Id { get; set; }
    public string Name { get; set; }
    public List<Edge> EdgeList { get; set; }
}

public class Edge
{
    public string Id { get; set; }
    public double Cost { get; set; }
}

When partially updating my Graph I want to find an existing Node in NodeList by it's Id, and update it's Name and Edge property. I do not want to add new Node objects in my NodeList. Only want to update existing ones.

Sofar I've tried:

public void UpdateGraph(string index, Graph graph)
{
    var docPath = new DocumentPath<Graph>(graph.Id).Index(index);
    try
    {
        var updateResp = client.Update<Graph, Graph>(docPath, searchDescriptor => searchDescriptor
            .Doc(graph)    
            .RetryOnConflict(4)
            .Refresh(true)
        );
    }
}

In my current implementation as you can see all I am doing is replacing the old Graph object. But I want to partially update my Graph object. I want to send list of Node object as parameter, Find those in NodeList and only update those Node Objects.

Maybe some thing like the following,

public void UpdateGraph(string index, List<Node> node)
{
    //Code here
}

Because NodeList is a List<Node>, a partial update is not possible as the provided value would replace the existing value.

You can however use optimistic concurrency control to

  1. get the existing document
  2. make the changes in your application
  3. index the changed document back into Elasticsearch, using the version number from the get request for optimistic concurrency

Something like the following will work

var getResponse = client.Get<Graph>("graph-id");

var graph = getResponse.Source;
var node = graph.NodeList.First(n => n.Id == "node-id");  

// make changes to the node
node.Name = "new name";
node.EdgeList.First().Cost = 9.99;

var indexResponse = client.Index(graph, i => i
    // specify the version from the get request
    .Version(getResponse.Version)
);

If the Graph has been changed in between the get and the index call, then a 409 response will be returned on the index call.

If you regularly need to update Nodes and Edges independently of one another, you may decide to model them with Parent/Child relationships which would allow you to update without needing to pull back the object graph and index the changes.