1st class patching in RavenDB 4.0
One of the most common operations in RavenDB is to load a document, make a simple change and save it back. Usually, we tell users to just rely on the change tracking on the session and just save the document, but while it is the easiest way, it isn’t always the best. If I have a large document, I might not want to send it all the way back to the server just for a small change. That is why RavenDB has had a Patch operation for a long time. But while we had this feature, it was always a bit clumsy. It either required you to build a patch request using a somewhat cryptic and limited object graph or to write your own inline javascript to make the modifications.
With RavenDB 4.0, we are introducing patching as a first class concept, baked directly into the session, for example:
In this case, we’ll send the server a request to update the last modified date when the SaveChanges method is called. The syntax is not all that I wish it could be, but we have to operate with the limitations that Linq syntax can accept.
A more interesting case is when you want to use patching not to reduce the network load, but to allow multiple concurrent operations on the document. Let us consider the case of adding a comment to this blog post. It is fine if two users post a comment at the same time, and we can express that using:
This gives us an easy way to express such things and expose a RavenDB capability that too few users has taken advantage of. Beneath the scenes, the Linq expressions are turned into JavaScript patches, which is then used to send just the right commands for the server to work with.
It’s a really cool feature, even if I so myself.
Comments
Why JS patches and not the older style of patch commands (set, add, inc, modify, etc.)? Wouldn't JS patches cause more load on the database server?
Mircea, Users found it hard to deal with complex stuff, and it is easier to have just a single code path that works for all cases
This is nice. How do you like this?
selector and values would have the same type T preventing many possible mistakes.
Tobi, You mean if I want to make a more complex changes?
How would this work with a collection as well?
I guess it sucks for collections :)
I like this idea VERY much. Am I right that currently patching (3.5) exists completely out of the session?
In any case having this syntax feels like it fits better in session management
Steven, You can do patching in the session in 3.5,
Session.Advanced.Defer(new ScriptedPatchCommand())
That is pretty much how we do this work, to be fair. But this is much much nicer.Tobi, We are going to merge all patches on the same document to a single script, you can just call it multiple times
Ugh, Defer, yet another feature I wish I'd known about. I'll be making use of it now AND I look forward to the new syntax :)
actually, what would also be nice is to get some way to use
UpdateByIndexAsync
in the same way.... by same way I mean, not done until SaveChanges is calledSteven, That is not something that we can do. The problem is that you might have a million changes in this operation, and we don't want to run it in a single tx.
Oh, I get it I think, that means Defer is part of the SaveChanges transaction. If something besides the Defer patch fails the Defer will fail too? If so, that's awesome.
Steven, Yes, exactly.
Comment preview