Error: the update operation document must contain atomic operators, when running updateOne

Mongodb

Mongodb Problem Overview


In my collection, there is only one document.

> db.c20160712.find()
{ "_id" : ObjectId("57ab909791c3b3a393e9e277"), "Dimension_id" : 2, "Attribute" : "good", "Hour" : "20160712_06", "Frequency_count" : 100 

I want to run updateOne to replace the document with another one. But why is there Error: the update operation document must contain atomic operators?

> db.c20160712.updateOne( { "Attribute" : "good"}, {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre" : "Action"}, { upsert: true} )
2016-08-10T16:37:57.089-0400 E QUERY    [thread1] Error: the update operation document must contain atomic operators :
DBCollection.prototype.updateOne@src/mongo/shell/crud_api.js:493:1
@(shell):1:1

The second and third arguments in the above command comes from an example in The Definitive Guide to MongoDB: A complete guide to dealing with Big Data ... By Eelco Plugge, David Hows, Peter Membrey, Tim Hawkins

My MongoDB is 3.2.

Mongodb Solutions


Solution 1 - Mongodb

Wrong syntax for the second parameter. Please check the docs. It should be:

db.c20160712.updateOne(
    { "Attribute" : "good" }, 
    { $set: {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre" : "Action" } },
    { upsert: true }
);

Solution 2 - Mongodb

I believe this was changed as a side-effect of introducing the updateOne() method in addition to update() and updateMany() as somewhat of a safeguard to prevent user's from accidentally overriding an entire document.

You can use the replaceOne() method instead, or an update() without specifying multi:true.

Solution 3 - Mongodb

You should use this code because I was also facing the same problem and then I used this code:

updateOne(
    { _id: new ObjectID(req.params.id) },
    { $set: { title: req.body.bookName, author: req.body.authorName } },
    { upsert: true }
)

and you should also define ObjectID otherwise the problem will occur again.

const ObjectID = require('mongodb').ObjectID;

Solution 4 - Mongodb

There are the "replaceX" methods, and the "updateX" methods.

The answer by @Alex Blex is of the update kind, while the PO was attempting (in 2016) to replace. Both are valid, albeit they work a bit differently.

The updateX methods, in their second argument, want a document like Alex's: { $set: {"Type" : "DVD"... } where I guess that $set is an instance of the atomic operators mentioned in the error msg.
With update you can target individual properties of the DB document, leaving the others unchanged.

The replace methods take a complete document as the second operand, intended to totally replace the current document existing in the DB.
In this case the second argument is simply the new document, in full. No $set or others (there are several, to delete, increment, ...).

In all cases, the first argument is a MongoDB search document, in my case I use the _id and prepare it like so:
let searchDoc = { _id: ObjectID( _id )};
As @nagender pratap chauhan mentioned, you can't use the _id's string value for matching.
Also, there is some confussion with ObjectID and ObjectId (upper- or lower- case "D").

The third argument, optional, contains the options.
In the case of the updateOne method, stating
{ upsert: true}
means that, in case there are no documents satisfying the search criteria stated in the first argument, Mongo should create it.

My code is like so:

let searchDoc = { _id: ObjectID( _id )};
this.data = await DAO.db.collection( 'authors' )
.replaceOne(
    searchDoc,                  // filter
    authorData,                 // replacement doc (a JS object)
    {                           // options
        returnOriginal: false,
        sort: [['_id', -1]],
    }
);

return this.data;               // the stored author

The _id field must not be present in the replacement document, else Mongo would complain about trying to change an immutable field, even if the value is the same as the existing one.

Solution 5 - Mongodb

You did the same mistake as I did. Upon going through the docs I realized the syntax is wrong. Try:

db.c20160712.updateOne( 
   { "Attribute" : "good"}, 
   {"Type" : "DVD", "Title" : "Matrix, The", "Released" : 1999, "Genre" : "Action"}, 
   { upsert: true} 
)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTimView Question on Stackoverflow
Solution 1 - MongodbAlex BlexView Answer on Stackoverflow
Solution 2 - MongodbdyoubergView Answer on Stackoverflow
Solution 3 - Mongodbnagender pratap chauhanView Answer on Stackoverflow
Solution 4 - MongodbJuan LanusView Answer on Stackoverflow
Solution 5 - MongodbPrasad NaikView Answer on Stackoverflow