0

I'm experiencing some unexpected behavior with respect to using the $set (doc1, doc2) operator to update arrays in MongoDB via rmongodb.

I tried to test this as systematic as possible with three different versions of the DB server (2.2.2, 2.2.3_rc0 and 2.2.3_rc1). I put details such as MongoDB's error log and my Platform Infos at the very end.

It'd be great if someone could verify this behavior and/or tell me what I'm doing wrong.

Example Document

Suppose we have the following document in our DB

_id : 7      5106887fe2be1937c1e3c8b0
host : 2     host1.com
array : 4    
    0 : 2    value1
    1 : 2    value2
    2 : 2    value3

I'd like to update the first array value (index = 0). It seems as if this only works if the new value does not differ "too much" from the previous value:

Update 1

Success

Change value value1 to VALUE1 in array array via "first match operator" ($)

b <- mongo.bson.from.list(list(
    host="host1.com",
    array="value1"
))

value.new <- "VALUE1"
bnew <- mongo.bson.from.list(list("$set"=list("array.$"=value.new)))
> bnew
    $set : 3     
        array.$ : 2      VALUE1
res <- mongo.update(mongo=con, ns=ns, criteria=b, objNew=bnew)
> res
[1] TRUE


b <- mongo.bson.from.list(list(
    host="host1.com",
    array=value.new
))
> mongo.find.one(mongo=con, ns=ns, query=b)
    _id : 7      5106887fe2be1937c1e3c8b0
    host : 2     host1.com
    array : 4    
        0 : 2    VALUE1
        1 : 2    value2
        2 : 2    value3

Failure

However, when I try to change VALUE1 to othervalue, the update fails

b <- mongo.bson.from.list(list(
    host="host1.com",
    array="VALUE1"
))
> mongo.find.one(mongo=con, ns=ns, query=b)
    _id : 7      5106887fe2be1937c1e3c8b0
    host : 2     host1.com
    array : 4    
        0 : 2    VALUE1
        1 : 2    value2
        2 : 2    value3
# >> query seems to be okay.

value.new <- "othervalue"
bnew <- mongo.bson.from.list(list("$set"=list("array.$"=value.new)))
> bnew
    $set : 3     
        array.$ : 2      othervalue

res <- mongo.update(mongo=con, ns=ns, criteria=b, objNew=bnew)
> res
[1] FALSE


b <- mongo.bson.from.list(list(
    host="host1.com",
    array=value.new
))
> mongo.find.one(mongo=con, ns=ns, query=b)
NULL

Update 2

Success

Change value VALUE1 to value1 in array array via position index

b <- mongo.bson.from.list(list(
    host="host1.com",
    array="value2"
))


value.new <- "value1"
bnew <- mongo.bson.from.list(list("$set"=list("array.0"=value.new)))
bnew
    $set : 3     
        array.0 : 2      value1

res <- mongo.update(mongo=con, ns=ns, criteria=b, objNew=bnew)
> res
[1] TRUE


b <- mongo.bson.from.list(list(
    host="host1.com",
    array=value.new
))
> mongo.find.one(mongo=con, ns=ns, query=b)
    _id : 7      5106887fe2be1937c1e3c8b0
    host : 2     host1.com
    array : 4    
        0 : 2    value1
        1 : 2    value2
        2 : 2    value3

Failure

Again, when I try to change the first array value to abcd, the update fails

value.new <- "abcd"
bnew <- mongo.bson.from.list(list("$set"=list("array.0"=value.new)))
bnew
    $set : 3     
        array.0 : 2      abcd

res <- mongo.update(mongo=con, ns=ns, criteria=b, objNew=bnew)
> res
[1] FALSE


b <- mongo.bson.from.list(list(
    host="host1.com",
    array=value.new
))
> mongo.find.one(mongo=con, ns=ns, query=b)
NULL

MongoDB's error log

Mon Jan 28 15:19:37 [conn1]  mytest.hosts Assertion failure x == _nfields src\mongo\db\jsobj.cpp 1250
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\util\stacktrace.cpp(182)                           mongo::printStackTrace+0x3e
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\util\assert_util.cpp(109)                          mongo::verifyFailed+0xdc
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\db\jsobj.cpp(1250)                                 mongo::BSONIteratorSorted::BSONIteratorSorted+0xf3
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\db\ops\update_internal.cpp(906)                    mongo::ModSetState::createNewFromMods+0xa3
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\db\ops\update.cpp(370)                             mongo::_updateObjects+0x15a2
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\db\instance.cpp(573)                               mongo::receivedUpdate+0x60d
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\db\instance.cpp(437)                               mongo::assembleResponse+0x626
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\db\db.cpp(193)                                     mongo::MyMessageHandler::process+0xf5
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\mongo\util\net\message_server_port.cpp(86)               mongo::pms::threadRun+0x59a
Mon Jan 28 15:19:37 [conn1] mongod.exe    ...\src\third_party\boost\libs\thread\src\win32\thread.cpp(180)  boost::`anonymous namespace'::thread_start_function+0x21
Mon Jan 28 15:19:37 [conn1] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\threadex.c(314)      _callthreadstartex+0x17
Mon Jan 28 15:19:37 [conn1] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\threadex.c(292)      _threadstartex+0x7f
Mon Jan 28 15:19:37 [conn1] kernel32.dll                                                                   BaseThreadInitThunk+0xd
Mon Jan 28 15:19:37 [conn1] update mytest.hosts query: { host: "host1.com", array: "VALUE1" } update: { $set: { array.$: "othervalue" } } nscanned:1 keyUpdates:0 exception: assertion src\mongo\db\jsobj.cpp:1250 locks(micros) w:343875 344ms
Mon Jan 28 15:20:06 [conn1]  mytest.hosts Assertion failure x == _nfields src\mongo\db\jsobj.cpp 1250
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\util\stacktrace.cpp(182)                           mongo::printStackTrace+0x3e
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\util\assert_util.cpp(109)                          mongo::verifyFailed+0xdc
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\db\jsobj.cpp(1250)                                 mongo::BSONIteratorSorted::BSONIteratorSorted+0xf3
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\db\ops\update_internal.cpp(906)                    mongo::ModSetState::createNewFromMods+0xa3
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\db\ops\update.cpp(370)                             mongo::_updateObjects+0x15a2
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\db\instance.cpp(573)                               mongo::receivedUpdate+0x60d
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\db\instance.cpp(437)                               mongo::assembleResponse+0x626
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\db\db.cpp(193)                                     mongo::MyMessageHandler::process+0xf5
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\mongo\util\net\message_server_port.cpp(86)               mongo::pms::threadRun+0x59a
Mon Jan 28 15:20:06 [conn1] mongod.exe    ...\src\third_party\boost\libs\thread\src\win32\thread.cpp(180)  boost::`anonymous namespace'::thread_start_function+0x21
Mon Jan 28 15:20:06 [conn1] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\threadex.c(314)      _callthreadstartex+0x17
Mon Jan 28 15:20:06 [conn1] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\threadex.c(292)      _threadstartex+0x7f
Mon Jan 28 15:20:06 [conn1] kernel32.dll                                                                   BaseThreadInitThunk+0xd
Mon Jan 28 15:20:06 [conn1] update mytest.hosts query: { host: "host1.com", array: "value2" } update: { $set: { array.0: "abcd" } } nscanned:1 keyUpdates:0 exception: assertion src\mongo\db\jsobj.cpp:1250 locks(micros) w:344363 345ms
Mon Jan 28 15:20:06 [journal] *** unhandled exception (access violation) at 0x0000000076D632D0, terminating
Mon Jan 28 15:20:06 [journal] *** access violation was a read from 0x0000008301570AD8
Mon Jan 28 15:20:06 [journal] *** stack trace for unhandled exception:
Mon Jan 28 15:20:06 [journal] ntdll.dll                                                                      RtlFreeHeap+0xd0
Mon Jan 28 15:20:06 [journal] kernel32.dll                                                                   HeapFree+0xa
Mon Jan 28 15:20:06 [journal] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\free.c(51)           free+0x1c
Mon Jan 28 15:20:06 [journal] mongod.exe    ...\src\mongo\db\d_concurrency.cpp(309)                          mongo::Lock::ScopedLock::~ScopedLock+0xac
Mon Jan 28 15:20:06 [journal] mongod.exe                                                                     mongo::Lock::GlobalRead::`scalar deleting destructor'+0x14
Mon Jan 28 15:20:06 [journal] mongod.exe    ...\src\mongo\db\dur.cpp(567)                                    mongo::dur::_groupCommitWithLimitedLocks+0x174
Mon Jan 28 15:20:06 [journal] mongod.exe    ...\src\mongo\db\dur.cpp(608)                                    mongo::dur::groupCommitWithLimitedLocks+0x24
Mon Jan 28 15:20:06 [journal] mongod.exe    ...\src\mongo\db\dur.cpp(743)                                    mongo::dur::durThreadGroupCommit+0x70
Mon Jan 28 15:20:06 [journal] mongod.exe    ...\src\mongo\db\dur.cpp(814)                                    mongo::dur::durThread+0x198
Mon Jan 28 15:20:06 [journal] mongod.exe    ...\src\third_party\boost\libs\thread\src\win32\thread.cpp(180)  boost::`anonymous namespace'::thread_start_function+0x21
Mon Jan 28 15:20:06 [journal] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\threadex.c(314)      _callthreadstartex+0x17
Mon Jan 28 15:20:06 [journal] mongod.exe    f:\dd\vctools\crt_bld\self_64_amd64\crt\src\threadex.c(292)      _threadstartex+0x7f
Mon Jan 28 15:20:06 [journal] kernel32.dll                                                                   BaseThreadInitThunk+0xd
Mon Jan 28 15:20:06 [journal] writing minidump diagnostic file mongo.dmp
Mon Jan 28 15:20:06 [journal] *** immediate exit due to unhandled exception

Platform Infos

OS: Windows 7 (64 Bit)

> sessionInfo()
R version 2.15.1 (2012-06-22)
Platform: i386-pc-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252   
[3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] rmongodb_1.0.5

loaded via a namespace (and not attached):
[1] tools_2.15.1

Only for those interested: this is the code that produced the example doc

#-------------------------------------------------------------------------------
# ENSURE PACKAGE
#-------------------------------------------------------------------------------

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

# /ENSURE PACKAGE ----------

#-------------------------------------------------------------------------------
# DB CONNECTION
#-------------------------------------------------------------------------------

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

# /DB CONNECTION ----------

#-------------------------------------------------------------------------------
# INSERT EXAMPLE DOCS
#-------------------------------------------------------------------------------

# ENSURE EMPTY DB
mongo.remove(mongo=con, ns=ns)
cursor  <- mongo.find(mongo=con, ns=ns)
out <- NULL
while (mongo.cursor.next(cursor=cursor)) {
    out <- c(out, list(mongo.cursor.value(cursor=cursor)))
}
out
# /

blist <- NULL

########
# DOC1 #
########
buf <- mongo.bson.buffer.create()
mongo.bson.buffer.append(buf, name="host", 
    value="host1.com") 
    mongo.bson.buffer.start.array(buf, "array")
    values <- list("value1", "value2", "value3")
    for (ii in seq(along=values)) {
        mongo.bson.buffer.append(
            buf=buf, 
            name=as.character(ii-1), 
            value=values[[ii]]
        )
    } 
    mongo.bson.buffer.finish.object(buf) # finish array
mongo.bson.buffer.finish.object(buf) # finish doc

b <- mongo.bson.from.buffer(buf)
blist <- c(blist, list(b))
blist

sapply(blist, function(ii) {
    mongo.insert(mongo=con, ns=ns, b=ii)
})

# TEST QUERY
cursor  <- mongo.find(mongo=con, ns=ns, query=b)
out <- NULL
while (mongo.cursor.next(cursor=cursor)) {
    out <- c(out, list(mongo.cursor.value(cursor=cursor)))
}
out

# /INSERT EXAMPLE DOCS ----------
4

1 に答える 1

0

Rappster さん、'R' の問題も 'rmongodb' の問題もありません。残念ながら、サーバー (mongod.exe) が再び混乱しています。ただし、mongod 2.2.2 (64 ビット) でこれを自分で試してみましたが、問題はありませんでした。アサーションが失敗しているコードを調べましたが、不適切な形式の BSON が渡されたり、どこかからメモリが破損したりしない限り、アサーションが失敗する理由がわかりませんでした。10gen の専門家の 1 人がこれを確認できるように、別のバグ レポートを提出する必要があるようです。ここでそれらを参照してください。あなたはすでに状況をよく説明しています。ありがとう。

于 2013-01-28T17:17:07.920 に答える