Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RavenDB Patch API: updating a nested collection

Tags:

patch

ravendb

I am trying to update a nested collection using the Patch API. More specifically, consider the following example - a Posts collection:

{
  "Title": "Hello RavenDB",
  "Category": "RavenDB",
  "Content": "This is a blog about RavenDB",
  "Comments": [
    {
      "Title": "Unrealistic",
      "Content": "This example is unrealistic"
    },
    {
      "Title": "Nice",
      "Content": "This example is nice"
    }
  ]
}

I used the Patch API and Set-based operation docs at http://ravendb.net/docs/client-api/partial-document-updates and http://ravendb.net/docs/client-api/set-based-operations as well as several stackoverflow questions as resources to do a bulk update using set operations and a static index. A requirement is to update the "Title" of a comment only when the previous value was "Nice" and if so, update it to "Bad".

The static index "NicePosts" is defined as:

Map = posts => from post in posts    
               where post.Comments.Any(comment => comment.Title == "Nice")
               select new {post.Title, post.Category}

The bulk patch update command is:

    documentStore.DatabaseCommands.UpdateByIndex("NicePosts",   
                    new IndexQuery(),                                               
           new[] { new PatchRequest 
                    {   Type = PatchCommandType.Modify,                          
                    Name = "Comments",  
                      PrevVal = RavenJObject.Parse(@"{ ""Title"": ""Nice""}"),
                      Nested = new[]
                              {
                                new PatchRequest {Type = PatchCommandType.Set, Name = "Title", Value = new RavenJValue("Bad") },
                       }  }, allowStale: true);

I have some questions regarding this:

1) Is my structure/syntax for the update command correct?

2) I would like the update to be performed on all the records in the collection. Hence I haven't defined the query filter in the IndexQuery Query because the "NicePosts" index already returns the appropriate set. However running this command doesn't update the collection.

3) If I set "allowStale:false" I get a "stale index" error. Before opening my document store session I instantiate the index class and Execute it to persist it to the ravenDB instance. Any ideas whats going wrong here?

Thanks,

EDIT:

Based on ayende's recommendation changed Patch command to:

 documentStore.DatabaseCommands.UpdateByIndex("NicePosts",
                                         new IndexQuery(),
                                         new[] {
                                                   new PatchRequest {
                                                     Type = PatchCommandType.Modify,
                                                     Name = "Comments",
                                                     Position = 0,
                                                     Nested = new[] {
                                                       new PatchRequest {Type = PatchCommandType.Set, Name = "Title", Value = new RavenJValue("Bad")},
                                                     }
                                                   }
                                                 }, allowStale: false);
like image 490
fjxx Avatar asked May 14 '12 23:05

fjxx


People also ask

Should I use put or patch for my API methods?

While the PUT method is a common and valid choice, it might not fit every situation. For example, when implementing the PUT method, we assume that the API users know all of the details of a particular entity. Since omitting single property results in removing it, they need to be careful. A solution to this issue can be the PATCH method.

How do I support partial updates (patches) in my APIs?

Use the ASP.NET Core Json Patch library to support partial updates (patches) in your APIs using JSON Patch operations. Nancy Support Shortly after publishing this post, Nancy core contributor and evangelist Jonathan Channonadded support for the ASP.NET Core JSON Patch library to Nancy. He moves fast, real fast. Similar articles:

How to implement a patch handler using Mongoose?

To implement a PATCH handler using Mongoose, we can use the findByIdAndUpdate method without the overwrite: true option. First, let’s use the @Patch decorator in our controller:

How to initialize a collection in the CANVAS app?

Collections in the Canvas App are considered a type of data source that used to store data locally in the app. You can initialize a collection by using the ClearCollect () function and define the collection data.


2 Answers

This can now be done using the scripted patch request:

string oldTitle = "Nice";
string newTitle = "Bad";

documentStore.DatabaseCommands.UpdateByIndex("NicePosts",   
    new IndexQuery(),                                               
    new ScriptedPatchRequest 
    {                       
        Script = @"for (var i = 0; i < this.Comments.length; i++)
                       if (this.Comments[i].Title == oldTitle)
                           this.Comments[i].Title = newTitle;",
        Values =
        {
            { "oldTitle", oldTitle },
            { "newTitle", newTitle },
        },
    }
);
like image 98
CMircea Avatar answered Nov 09 '22 23:11

CMircea


You can't use the patch command to update values based on the existing value in the array. You need to specify the actual position.

like image 37
Ayende Rahien Avatar answered Nov 10 '22 01:11

Ayende Rahien