Closed maxto closed 6 years ago
The update api was switched in this commit from the deprecated mongoc_collection_update()
to the new mongoc_collection_update_one()
in order to support optional array filters.
It could be a bug in mongoc_collection_update_one
in the c driver, or perhaps this is a feature? In this SO topic it is stated that: You can only modify multiple documents using the $ modifier operators. You probably had something like this:
> db.coll.update({ }, { a: 'b' }, false, true);
Which would normally replace the first object in the collection with { a: 'b' } if multi was false. You wouldn't want to replace all the objects in your collection with the same document!
Use the $set operator instead:
> db.coll.update({ }, { '$set': { a: 'b' } }, false, true);
This will set the a property of every document (creating it as necessary) to 'b'.
Thank for your answer @jeroen . I saw the c driver, but it's not a bug, in the official mongodb doc there are 4 methods
db.collection.update() (probably deprecated as you stated)
db.collection.updateOne(<filter>, <update>, <options>) (update one doc)
db.collection.updateMany(<filter>, <update>, <options>) (update multi)
db.collection.replaceOne(<filter>, <replacement>, <options>) (replace one doc)
So we miss a method in mongolite, the last one (replaceOne) to replace a whole document. Is it right or you've been working on it? Thks
That is correct I haven't implemented replace yet. However you are trying to do an update rather than a replacement , correct?
Yes I do. I build a package as wrapper of mongolite to do many scheduled tasks with update
method, everthing's broken on 22 dec, but i've already modified the main code following the new api methods. I only need to know if you want to maintain up the old update
method, in order to change my package functions with new atomic update_one
and replace_one
(for the last one i'll do a temporary trick,waiting for your implementation) thks
I have added a new replace
method. Could you help me test this?
devtools::install_github("jeroen/mongolite")
Here is some example code:
con <- mongolite::mongo()
con$drop()
con$insert(c(
'{"num":1234,"name":"Max"}',
'{"num":1235,"name":"Jerry"}'
))
# Should error
con$update(query = '{"num":1234}', update = '{"name":"Jim"}')
# Replace record
con$replace(query = '{"num":1234}', update = '{"name":"Jim"}')
# Replace with upsert
con$replace(query = '{"num":9999}',update = '{"name":"Peter"}', upsert = TRUE)
con$replace(query = '{"num":1235}',update = '{"name":"Jerry"}', upsert = TRUE)
Just tried the tests but it asked for $ operator, so basically the same functionality as update.
{
"_id" : ObjectId("5a4ab9789550831b20004aa5"),
"num" : 1234,
"name" : "Max"
}
{
"_id" : ObjectId("5a4ab9789550831b20004aa6"),
"num" : 1235,
"name" : "Jerry"
}
con$update(query = '{"num":1234}', update = '{"name":"Jim"}')
Error: Invalid key 'name': update only works with $ operators
con$replace(query = '{"num":1234}', update = '{"name":"Jim"}')
Error: Invalid key 'name': update only works with $ operators
con$replace(query = '{"num":1234}', update = '{"$set":{"name":"Jim"}}')
List of 2
$ modifiedCount: int 1
$ matchedCount : int 1
{
"_id" : ObjectId("5a4ab9789550831b20004aa5"),
"num" : 1234,
"name" : "Jim"
}
con$replace(query = '{"num":9999}',update = '{"name":"Peter"}', upsert = TRUE)
Error: Invalid key 'name': update only works with $ operators
con$replace(query = '{"num":9999}',update = '{"$set":{"name":"Peter"}}', upsert = TRUE)
List of 3
$ modifiedCount: int 0
$ matchedCount : int 0
$ upsertedId : chr "5a4abb6f35f29ef10f063ba9"
{
"_id" : ObjectId("5a4abb6f35f29ef10f063ba9"),
"num" : 9999,
"name" : "Peter"
}
con$replace(query = '{"num":1235}',update = '{"name":"Jerry"}', upsert = TRUE)
Error: Invalid key 'name': update only works with $ operators
con$replace(query = '{"num":1235}',update = '{"$set":{"name":"Jerry"}}', upsert = TRUE)
List of 2
$ modifiedCount: int 0
$ matchedCount : int 1
I also tried
con$replace(query = '{"num":1235}', update = '{"$set":{"height":190,"age":30}}')
{
"_id" : ObjectId("5a4ab9789550831b20004aa6"),
"num" : 1235,
"name" : "Jerry",
"height" : 190,
"age" : 30
}
Note: with mongodb 3.4.9 the replace
method crashed Rstudio. With mongodb 3.6.1 and mongolite 1.2 the update
method crashed, too. I guess there are some conflicts in C driver api , so it needs to be careful about server and api versions.
That's very strange, it should never crash. I have tested this on MongoDB 3.2, 3.4 and 3.6 and it all seems OK.
Perhaps your installation got corrupted. Can you try reinstalling the dev version not of mongolite, making sure mongolite is not loaded while you install it? This is especially important on Windows.
Also which version of r and rstudio do you use? Make sure you are up to date.
R version 3.4.3 (2017-11-30)
Rstudio: Version 1.1.383
MongoDB: 3.6.1
Mongolite: v1.4.9
yes i installed with mongolite-stable unloaded, i tried with a clean mongolite dev installation and c mongodb downgraded to 3.4.1 and it'fine, i guess a Windows (tried on win7 and win10) issue managing mongolite installations from github (no issues from CRAN) compiling with RbuildTools
Now it's fine, the replace
method works, but i cannot replicate the error anymore, Windows alway makes me happy with these stuff :) thank you
con$replace(query = '{"num":1234}', update = '{"name":"Jim"}')
List of 2
$ modifiedCount: int 1
$ matchedCount : int 1
{
"_id" : ObjectId("5a4b3e4d007bf321c8000712"),
"name" : "Jim"
}
Mongo collection update doesn't work without $ operators after the last mongolite release
So, we lost the replace method for the whole object with 1 query and we need to work always in atomic way, but that's not always the case
Instead with the previous release