4

I'm trying to patch a single/multiple documents (identified by their id) with that I receive in a Dictionary<string, object>. The key of the dictionary is the path to the document property to update, and it may even be a subpath.

So if my document looks like this:

public class MyDoc
{
    public string StringProp {get; set;}
    public bool? BoolProp {get; set;}
    public int? IntProp {get; set;}
    public SubDocument SubProp {get; set;}
}

public class SubDocument
{
    public string StringProp {get; set;}
}

So an example Dictionary may be:

new Dictionary<string, object> 
{ 
    {"StringProp", "hello" },
    {"BoolProp", true },
    {"SubProp.StringProp", "subprop value" },
}

I know how to fetch the document(s), apply the dictionary to it and save the document(s), but I'm looking for a way that doesn't require the extraction of the documents I want to modify.

I'm guessing it would go something along these lines:

 var operation = store
    .Operations
    .Send(new PatchByQueryOperation(new IndexQuery
    {
        QueryParameters = new Parameters
        {
            {"ids", new[] {"orders/1-A", "companies/1-A"}}
        },
         Query = @"from @all_docs as d where id() in ($ids)
          update
          {
              d.StringProp = 'hello';
              d.BoolProp = true;
              d.SubProp.StringProp = 'subprop value';
          }"
}));

And what if SubProp doesn't exist on a document or if I'd like to assign the entire SubProp rather than just fill a property on a subdocument?

1 Answer 1

2

Regarding your second Question about:
"assigning the entire SubProp rather than just filling a property on a subdocument"

The following will work:

var subObject = new SubDocument() {StringProp = "new sub text"};

var operation = store.Operations.Send(new PatchByQueryOperation(new IndexQuery
{
    QueryParameters = new Parameters
    {
        { "ids", new[] {"myDocs/1", "companies/1-A"} },
        { "subObject", subObject }
    },
    Query = @"from @all_docs as d where id() in ($ids)
                  update
                  {
                      d.StringProp = 'hello';
                      d.BoolProp = false;
                      d.SubProp = ($subObject);
                  }"
}));

Regarding your first Question about:
"what if SubProp doesn't exist on a document"

1. Patching with d.SubProp = 'value1' when SubProp doesn't exist, will succeed and property SubProp will be created with value1.

2. Patching with d.SubProp.StringProp = 'value2' will only succeed if property SubProp is an object type (not a string).


If you need to patch only a single document, then you don't have to use set-based patching.
You can use single-document patching.

Single-document patching is explained by these articles:
(Note: the Node.js article is currently more organized and detailed, the C# article is TBD,
however logic behind is the same)

https://ravendb.net/docs/article-page/latest/nodejs/client-api/operations/patching/single-document https://ravendb.net/docs/article-page/latest/csharp/client-api/operations/patching/single-document

Sign up to request clarification or add additional context in comments.

1 Comment

WRT the second part of your answer. In my original question you can see the dictionary that holds what I want to patch. This is the same for single document and multi-document patching. The Patch API on session.Advanced is typed, so it requires two type parameters I don't have in my dictionary (and I can only get a Type, not the T syntax). So, I'd need to be able to build an expression for 'set property X to Y' somehow. Something like PatchGeneric<T>(string entityId, string propertyPath, object value).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.