Reputation: 99478
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.
Upvotes: 162
Views: 224715
Reputation: 9
If you want to update all then use empty curly braces before $set
example:-
db.student_info.updateMany({},{$set:{"fine":0,"maxbook":3}},{upsert:true})
I faced the same error because I use this:-
db.student_info.updateMany({$set:{"fine":0,"maxbook":3}},{upsert:true})
Upvotes: 0
Reputation: 2344
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.
Upvotes: 5
Reputation: 2204
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;
Upvotes: 48
Reputation: 2332
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
.
Upvotes: 50