-
Type: New Feature
-
Resolution: Won't Do
-
Priority: Major - P3
-
None
-
Affects Version/s: 1.8.2
-
Component/s: Write Ops
-
Environment:All
-
Query
According to the documentation, this limitation currently applies to upserts:
<quote>
The positional operator cannot be combined with an upsert since it requires
a matching array element. If your update results in an insert then the "$"
will literally be used as the field name.
</quote>
When performing a findAndModify it would be incredibly powerful to support the insert condition for a document that does not exist. It would save on multiple calls to the Mongo Server and allow for a single atomic update/insert for a document with embedded arrays.
Below is JavaScript that can be run in the Mongo Shell to demonstrate this powerful capability:
The purpose of these documents is keep track of the last login per user per type of login. And to create the user document if it does not already exist in a single atomic transaction.
db.user_identities.ensureIndex({"user" : 1}, {unique : true}); db.user_identities.save({ user: 'user1', first_seen: 'date1', last_seen: [ { type: 'TA', date: 'date1' } ] }) db.user_identities.save({ user: 'user2', first_seen: 'date2', last_seen: [ { type: 'TA', date: 'date2' }, { type: 'PP', date: 'date3' } ] }) db.user_identities.save({ user: 'user3', first_seen: 'date3', last_seen: [ { type: 'TA', date: 'date3' }, { type: 'PP', date: 'date4' } ] }) // Existing entry - Works as expected db.user_identities.findAndModify({ query: {"user":"user3", "last_seen" : {$elemMatch : {"type": "PP", "date" : { $lte: "date4"} }}}, update: {$set: {"last_seen.$":{ type: 'PP', date: 'date5' }}}, upsert: true, "new": true}) /* Returns the following: { "_id" : ObjectId("4e034dd979ee2fd2e506ce24"), "user" : "user3", "first_seen" : "date3", "last_seen" : [ { "type" : "TA", "date" : "date3" }, { "type" : "PP", "date" : "date5" } ] } */ // Non-existent - Inserts the $ as the element name in the new document db.user_identities.findAndModify({ query: {"user":"user4", "last_seen" : {$elemMatch : {"type": "PP", "date" : { $lte: "date6"} }}}, update: {$set: {"last_seen.$":{ type: 'PP', date: 'date6' }}}, upsert: true, "new": true}) /* Returns: { "_id" : ObjectId("4e034dd9f0e57cca9b6f045a"), "last_seen" : { "$" : { "type" : "PP", "date" : "date6" } }, "user" : "user4" } */
- is duplicated by
-
SERVER-38729 Make $setOnInsert work with upserts and positional array updates
- Closed
- related to
-
SERVER-6566 Support conditional updates: $updates
- Closed