Reputation: 945
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
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
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