RavenDB version 2.5. Other versions:

Set based operations

Sometimes we need to update or delete a large amount of documents answering some criteria. With SQL this is a natural operation, and a query doing that will look like this:

DELETE FROM Users WHERE LastLogin < '2009-01-01'
UPDATE Users SET IsActive = 0 WHERE LastLogin < '2010-01-01'

This is usually not the case for NoSQL databases, where batch operations are not supported. RavenDB does support this, and by passing it a query and an operation definition, it will run the query and perform that operation on it's results.

The same queries and indexes that are used for data retrieval are used for the batch operations, therefore the syntax for defining which documents to do work on is exactly the same as you'd specify for those documents to be pulled from store.

The Delete operation

To issue a batch-delete command you need to specify an index, and a query to be sent to it. To minimize the chances of stale results coming back, bulk operations should only be performed on static indexes:

    											 new IndexQuery
    												 Query = "Title:RavenDB" // where entity.Title contains RavenDB
    											 }, allowStale: false);

The Update operation (Patching API)

Performing a mass-update is exactly the same as making a mass-delete, but this time it uses the Patching API to make it easy for us to define what to do with the documents matching our query:

    											 new IndexQuery { Query = "Title:RavenDB" },
                                                 		new PatchRequest
                                                 				Type = PatchCommandType.Add,
                                                 				Name = "Comments",
                                                 				Value = "New automatic comment we added programmatically"
                                                 	}, allowStale: false);

Complex Set-based update operations using ScriptedPatchRequest

As the ScriptedPatchRequest is part of the Patching API, it can also be used on Set-based operations:

    // Replace FirstName and LastName properties by FullName property
    	new IndexQuery { Query = "Tag:Users" },
    	new ScriptedPatchRequest()
    		Script = @"
    			this.FullName = this.FirstName + ' ' + this.LastName;
    			delete this.FirstName;
    			delete this.LastName;

Set-based operations and stale indexes

By default, set-based operations will not work on indexes that are stale, and the operation will only succeed if the specified index is NOT stale. This is to make sure you only delete what you intended to delete, and is part of RavenDB's safe-by-default approach.

For indexes that are updated all the time, you can set a Cutoff in the IndexQuery object you send, and that will make sure the operation is executed and that you know what results to expect.

When you absolutely certain you can perform the operation also when the index is stale, simply set the allowStale parameter to true.

Comments add new comment

The comments section is for user feedback or community content. If you seek assistance or have any questions, please post them at our support forums.

REPLY Posted by Jon on

This posts suggests we use Query/LuceneQuery to do create the query for these operations. Is that right and how would that look?

Ayende Rahien
REPLY Posted by Ayende Rahien on

new IndexQuery { Query = session.Query<User>().Where(x=>x.IsActive).ToString() }

REPLY Posted by Jon on

Oops - this post https://groups.google.com/forum/?fromgroups#!topic/ravendb/GFK3sIJB34Q

REPLY Posted by Eugene on

What should IndexName is my database name is Studies

REPLY Posted by eugene on

Is it possible to update every single value of property by pulling it up by property value?

Gayatri Kotamraju
REPLY Posted by Gayatri Kotamraju on

Do bulk operations perform any lockin?. If so how do you guarantee better performance? Are these bulk operations internally queued?

Dan Turner
REPLY Posted by Dan Turner on

Are these operations transactional? Is the UpdateByIndex call synchronous?