Given a document like;
{
"name": "Jason",
"foo": "bar",
"version": 3,
// ...
}
Is it possible to specify an update aggregation pipeline to conditionally update the entire document based on a property of the current document? i.e. to specify something like;
const newDocument = { ...currentDocument, version: 4, foo: "baz" };
if (document.version == 3)
$replaceRoot(newDocument)
else
doNothing()
The marked answer below does address this question. For the sake of being thorough I would like to add some context as to why this question was asked as the answer will slightly change.
CosmosDB provides the feature of Optimistic Concurrency Control (OCC) that allows CosmosDB to reject a command on a document if the document has changed unexpectedly. Important to note that the client can supply the expected version (_etag property) of the document.
MongoDB does use this feature under the hood, but does not expose OCC to the client. This means that your entire document change needs to be described in the Mongo Update pipeline syntax. This syntax is okay for simple documents and update commands. But, it is not a replacement for testable business logic code.
To expose OCC to the client when using MongoDB use a version property or similar and ensure to target the expected version in the command filter as described here.
Yes it can, you can build the update pipeline in code like you did but you can also do it in Mongo with $cond like so:
db.collection.updateOne({},
[
{
$replaceRoot: {
newRoot: {
$cond: [
{
$eq: [
"$version",
3
]
},
{
$mergeObjects: [
"$$ROOT",
{
version: 4,
foo: "baz"
}
]
},
"$$ROOT"
]
}
}
}
])