Skip to main content

Commands: Patches: How to use JavaScript to patch your documents?

Patch command is used to perform partial document updates without having to load, modify, and save a full document. This is usually useful for updating denormalized data in entities.

Syntax

/// <summary>
/// Sends a patch request for a specific document, ignoring document's Etag and if it is missing
/// </summary>
/// <param name="key">Key of the document to patch</param>
/// <param name="patch">The patch request to use (using JavaScript)</param>
RavenJObject Patch(string key, ScriptedPatchRequest patch);

/// <summary>
/// Sends a patch request for a specific document, ignoring the document's Etag
/// </summary>
/// <param name="key">Key of the document to patch</param>
/// <param name="patch">The patch request to use (using JavaScript)</param>
/// <param name="ignoreMissing">true if the patch request should ignore a missing document, false to throw DocumentDoesNotExistException</param>
RavenJObject Patch(string key, ScriptedPatchRequest patch, bool ignoreMissing);

/// <summary>
/// Sends a patch request for a specific document
/// </summary>
/// <param name="key">Key of the document to patch</param>
/// <param name="patch">The patch request to use (using JavaScript)</param>
/// <param name="etag">Require specific Etag [null to ignore]</param>
RavenJObject Patch(string key, ScriptedPatchRequest patch, Etag etag);

/// <summary>
/// Sends a patch request for a specific document which may or may not currently exist
/// </summary>
/// <param name="key">Id of the document to patch</param>
/// <param name="patchExisting">The patch request to use (using JavaScript) to an existing document</param>
/// <param name="patchDefault">The patch request to use (using JavaScript) to a default document when the document is missing</param>
/// <param name="defaultMetadata">The metadata for the default document when the document is missing</param>
RavenJObject Patch(string key, ScriptedPatchRequest patchExisting, ScriptedPatchRequest patchDefault, RavenJObject defaultMetadata);

Parameters

public class ScriptedPatchRequest
{
/// <summary>
/// JavaScript function that will patch a document
/// </summary>
/// <value>The type.</value>
public string Script { get; set; }

/// <summary>
/// Additional values that will be passed to function
/// </summary>
public Dictionary<string, object> Values { get; set; }
}

Methods, objects and variables

Before we will move to the examples, let's look at the methods, objects, and variables available:

| ------ |:------:| ------ | | __document_id | variable | Id for current document | | this | object | Current document (with metadata) | | LoadDocument(key) | method | Allows document loading, increases maximum number of allowed steps in script. See Raven/AdditionalStepsForScriptBasedOnDocumentSize here. | | PutDocument(key, data, metadata) | method | Allows document putting, returns generated key | | IncreaseNumberOfAllowedStepsBy(number) | method | Will increase the maximum allowed number of steps in script by given value. Only available if Raven/AllowScriptsToAdjustNumberOfSteps is set to true. | | _ | object | Lo-Dash 2.4.1 | | trim() | string.prototype | trims the string e.g. this.FirstName.trim() | | output(...) | method | Allows debug your patch, prints passed messages in output tab | | indexOf(...) | Array.prototype | wrapper for _.indexOf | | filter(...) | Array.prototype | wrapper for _.filter | | Map(...) | Array.prototype | wrapper for _.map | | Where(...) | Array.prototype | wrapper for _.filter | | RemoveWhere(...) | Array.prototype | wrapper for _.remove returning Array for easier chaining | | Remove(...) | Array.prototype | wrapper for _.pull returning Array for easier chaining |

Custom functions

Beside built-in functions, custom ones can be introduced. Please visit this page if you want to know how to add custom functions.

Example I

// change FirstName to Robert
store
.DatabaseCommands
.Patch(
"employees/1",
new ScriptedPatchRequest
{
Script = "this.FirstName = 'Robert';"
});

Example II

// trim FirstName
store
.DatabaseCommands
.Patch(
"employees/1",
new ScriptedPatchRequest
{
Script = "this.FirstName = this.FirstName.trim();"
});

Example III

// add new property Age with value of 30
store
.DatabaseCommands
.Patch(
"employees/1",
new ScriptedPatchRequest
{
Script = "this.Age = 30;"
});

Example IV

// add new property Age with value of 30 using LoDash
store
.DatabaseCommands
.Patch(
"employees/1",
new ScriptedPatchRequest
{
Script = "_.extend(this, { 'Age': '30'});"
});

Example V

// passing data and loading different document
store
.DatabaseCommands
.Patch(
"employees/1",
new ScriptedPatchRequest
{
Script = @"
var employee = LoadDocument(differentEmployeeId);
this.FirstName = employee.FirstName;",
Values = new Dictionary<string, object>
{
{ "differentEmployeeId", "employees/2" }
}
});

Example VI

// accessing metadata (added ClrType property with value from @metadata)
store
.DatabaseCommands
.Patch(
"employees/1",
new ScriptedPatchRequest
{
Script = @"this.ClrType = this['@metadata']['Raven-Clr-Type'];"
});

Example VII

// creating new document with auto-assigned key e.g. 'Comments/100'. Document key will be returned by PutDocument.
store
.DatabaseCommands
.Patch(
"employees/1",
new ScriptedPatchRequest
{
Script = @"var commentKey = PutDocument('Comments/', { 'Author': this.LastName }, { });"
});

Example VIII

// add a new comment to Comments
store
.DatabaseCommands
.Patch(
"blogposts/1",
new ScriptedPatchRequest
{
Script = @"this.Comments.push({ 'Title': 'Some title', 'Content': 'Lore ipsum' });"
});

Example IX

// removing comments with 'Some title' as a title
store
.DatabaseCommands
.Patch(
"blogposts/1",
new ScriptedPatchRequest
{
Script = @"
this.Comments.RemoveWhere(function(comment) {
return comment.Title == 'Some title';
});"
});

Example X

// modifying each comment
store
.DatabaseCommands
.Patch(
"blogposts/1",
new ScriptedPatchRequest
{
Script = @"
this.Comments.Map(function(comment) {
comment.Title = 'New title';
return comment;
});"
});

Example XI

// increasing maximum number of allowed steps
store
.DatabaseCommands
.Patch(
"employees/1",
new ScriptedPatchRequest
{
Script = @"
var employee = LoadDocument(differentEmployeeId);
if (employee) {
IncreaseNumberOfAllowedStepsBy(10);
this.FirstName = employee.FirstName;
}",
Values = new Dictionary<string, object>
{
{ "differentEmployeeId", "employees/2" }
}
});