Reputation: 13080
I stumbled upon some issues regarding the function handling updates (mongo.update()
).
As I'm still in the middle of getting familiar with both MongoDB and the rmongodb package, the illustrated issues might all very well be due to my lack of knowledge ;-)
Ensuring that package is loaded
pkg <- "rmongodb"
lib <- file.path(R.home(), "library")
if (!suppressWarnings(require(pkg, lib.loc=lib, character.only=TRUE))) {
install.packages(pkg, lib=lib)
require(pkg, lib.loc=lib, character.only=TRUE)
}
Global variables
db <- "__test"
ns.0 <- "user"
ns <- paste(db, ns.0, sep=".")
con <- mongo.create(db=db)
Ensure emtpy DB
mongo.remove(mongo=con, ns=ns,
criteria=mongo.bson.from.list(lst=list(namefirst="John")))
Insert document
fields <- list(namefirst="John", namelast="Doe")
b <- mongo.bson.from.list(lst=fields)
mongo.insert(mongo=con, ns=ns, b=b)
if (is.null(mongo.find.one(mong=con, ns=ns, query=b))) {
stop("Something went wrong")
}
Update/upsert a document
criteria <- list(namefirst="John", namelast="Smith")
fields <- list(namefirst="John", namelast="Smith", age=30)
b <- mongo.bson.from.list(lst=fields)
crit <- mongo.bson.from.list(lst=criteria)
mongo.update(mongo=con, ns=ns, criteria=crit, objNew=b,
flags=mongo.update.upsert)
if (is.null(mongo.find.one(mong=con, ns=ns, query=b))) {
stop("Something went wrong")
}
List available docs
criteria <- list(namefirst="John")
crit <- mongo.bson.from.list(lst=criteria)
cursor <- mongo.find(mongo=con, ns=ns, query=crit)
out <- NULL
while (mongo.cursor.next(cursor=cursor)) {
bson <- mongo.cursor.value(cursor=cursor)
out <- c(out, list(bson))
}
> out
[[1]]
_id : 7 50f484fe3c3b8b8e3daa72e0
namefirst : 2 John
namelast : 2 Doe
[[2]]
_id : 7 50f484ff3c3b8b8e3daa72e1
namefirst : 2 John
namelast : 2 Smith
age : 1 30.000000
At this point, there are two docs in the collection which is what we'd expect.
0
)criteria <- list(namefirst="John")
fields <- list(age=99)
b <- mongo.bson.from.list(lst=fields)
crit <- mongo.bson.from.list(lst=criteria)
mongo.update(mongo=con, ns=ns, criteria=crit, objNew=b)
cursor <- mongo.find(mongo=con, ns=ns, query=crit)
out <- NULL
while (mongo.cursor.next(cursor=cursor)) {
bson <- mongo.cursor.value(cursor=cursor)
out <- c(out, list(mongo.bson.to.list(bson)))
}
if (out[[1]]$age != 99) {
stop("Something went wrong")
}
> out
[[1]]
[[1]]$`_id`
{ $oid : "50f484ff3c3b8b8e3daa72e1" }
[[1]]$namefirst
[1] "John"
[[1]]$namelast
[1] "Smith"
[[1]]$age
[1] 30
After performing the update, there's only one document left.
2
)Start over from scratch as previous update seems to have corrupted the DB:
Ensure empty DB
mongo.remove(mongo=con, ns=ns,
criteria=mongo.bson.from.list(lst=list(namefirst="John")))
Insert document
fields <- list(namefirst="John", namelast="Doe")
b <- mongo.bson.from.list(lst=fields)
mongo.insert(mongo=con, ns=ns, b=b)
if (is.null(mongo.find.one(mong=con, ns=ns, query=b))) {
stop("Something went wrong")
}
Update/upsert document
criteria <- list(namefirst="John", namelast="Smith")
fields <- list(namefirst="John", namelast="Smith", age=30)
b <- mongo.bson.from.list(lst=fields)
crit <- mongo.bson.from.list(lst=criteria)
mongo.update(mongo=con, ns=ns, criteria=crit, objNew=b,
flags=mongo.update.upsert)
if (is.null(mongo.find.one(mong=con, ns=ns, query=b))) {
stop("Something went wrong")
}
Trying to update multiple documents. What I'm after here is to change the value for age
to 99
in both collections
criteria <- list(namefirst="John")
fields <- list(age=99)
b <- mongo.bson.from.list(lst=fields)
crit <- mongo.bson.from.list(lst=criteria)
mongo.update(mongo=con, ns=ns, criteria=crit, objNew=b,
flags=mongo.update.multi)
cursor <- mongo.find(mongo=con, ns=ns, query=crit)
out <- NULL
while (mongo.cursor.next(cursor=cursor)) {
bson <- mongo.cursor.value(cursor=cursor)
out <- c(out, list(mongo.bson.to.list(bson)))
}
Investigating the current DB state
> out
[[1]]
[[1]]$`_id`
{ $oid : "50f485cd3c3b8b8e3daa72e2" }
[[1]]$namefirst
[1] "John"
[[1]]$namelast
[1] "Doe"
[[2]]
[[2]]$`_id`
{ $oid : "50f485ce3c3b8b8e3daa72e3" }
[[2]]$namefirst
[1] "John"
[[2]]$namelast
[1] "Smith"
[[2]]$age
[1] 30
> sapply(out, function(ii) ii$age)
[[1]]
NULL
[[2]]
[3] 30
I would expect both docs to have age = 99
.
Upvotes: 1
Views: 1537
Reputation: 151
In both "potential bugs", you are updating the record to one that contains only the age field. Your records still exist, but they have no namefirst fields (or any other field besides age and _id) to match the later query. mongo.update() normally replaces the entire document, not selected fields. Your 2nd example could be coded like this:
criteria <- list(namefirst="John")
fields <- list(age=99)
b <- mongo.bson.from.list(lst=list('$set'=fields))
crit <- mongo.bson.from.list(lst=criteria)
mongo.update(mongo=con, ns=ns, criteria=crit, objNew=b,
flags=mongo.update.multi)
to set only desired fields. See http://docs.mongodb.org/manual/applications/update for more information.
Btw, though your example is very clear, you may write this much more succinctly as:
mongo.update(con, ns, list(namefirst="John"),
list('$set'=list(age=99)), mongo.update.multi)
Upvotes: 6