fjxx
fjxx

Reputation: 945

RavenDB Patch API: updating a nested collection

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);

Upvotes: 7

Views: 3650

Answers (2)

CMircea
CMircea

Reputation: 3568

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 },
        },
    }
);

Upvotes: 10

Ayende Rahien
Ayende Rahien

Reputation: 22956

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.

Upvotes: 3

Related Questions