nest for elasticsearch version 2.0.0.0 partial upd

2019-09-12 19:11发布

问题:

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
}

回答1:

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.