1

関数処理の更新に関するいくつかの問題に遭遇しました(mongo.update())。

免責事項

私はまだMongoDBrmongodbパッケージの両方に精通している最中なので、図解されている問題はすべて私の知識不足が原因である可能性があります;-)

準備

パッケージがロードされていることを確認する

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)
}

グローバル変数

db      <- "__test"
ns.0    <- "user"
ns      <- paste(db, ns.0, sep=".")
con     <- mongo.create(db=db)

DBの初期状態を作成する

emtpyDBを確認します

mongo.remove(mongo=con, ns=ns, 
    criteria=mongo.bson.from.list(lst=list(namefirst="John")))

ドキュメントを挿入

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")
}

ドキュメントを更新/アップサートする

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")
}

利用可能なドキュメントを一覧表示

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

この時点で、コレクションには2つのドキュメントがあります。これは私たちが期待していることです。

問題#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

更新を実行した後、残っているドキュメントは1つだけです。

問題#2:「マルチ」フラグ値で更新(2

以前の更新でDBが破損したようであるため、最初からやり直してください。

空のDBを確認します

mongo.remove(mongo=con, ns=ns, 
    criteria=mongo.bson.from.list(lst=list(namefirst="John")))

ドキュメントを挿入

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")
}

ドキュメントの更新/アップサート

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")
}

複数のドキュメントを更新しようとしています。ここで私が求めているのは、両方のコレクションの値を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)))
}

現在のDB状態の調査

> 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

私は両方のドキュメントが持っていることを期待しますage = 99

4

1 に答える 1

6

両方の「潜在的なバグ」で、レコードを年齢フィールドのみを含むレコードに更新しています。レコードはまだ存在しますが、後のクエリに一致するnamefirstフィールド(またはageと_id以外の他のフィールド)はありません。mongo.update()は通常、選択されたフィールドではなく、ドキュメント全体を置き換えます。2番目の例は、次のようにコーディングできます。

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)

必要なフィールドのみを設定します。詳細については、 http://docs.mongodb.org/manual/applications/updateを参照してください。

ところで、あなたの例は非常に明確ですが、これをもっと簡潔に次のように書くことができます。

mongo.update(con, ns, list(namefirst="John"),
                      list('$set'=list(age=99)), mongo.update.multi)
于 2013-01-15T00:14:25.833 に答える