简体   繁体   English

更新MongoDB(rmongodb)中的多个文档

[英]Update multiple documents in MongoDB (rmongodb)

I stumbled upon some issues regarding the function handling updates ( mongo.update() ). 我偶然发现了有关函数处理更新的一些问题( mongo.update() )。

Disclaimer 免责声明

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 ;-) 由于我仍在熟悉MongoDBrmongodb软件包,因此说明的问题很可能是由于我缺乏知识;-)

Preparations 准备工作

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)

Creating the initial state of the 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. 此时,集合中有两个文档,这正是我们所期望的。

Issue #1: update with default flag value ( 0 ) 问题1:使用默认标志值( 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. 执行更新后,只剩下一个文档。

Issue #2: update with "multi" flag value ( 2 ) 问题2:使用“多”标志值更新( 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 我要做的是将两个收藏中的age值都更改为99

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 . 我希望两个文档的age = 99

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. 您的记录仍然存在,但是它们没有namefirst字段(或age和_id以外的任何其他字段)来匹配后面的查询。 mongo.update() normally replaces the entire document, not selected fields. mongo.update()通常替换整个文档,而不是所选字段。 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. 有关更多信息,请参见http://docs.mongodb.org/manual/applications/update

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM