0

$set在使用( doc1 , doc2 ) 运算符通过rmongodb更新MongoDB中的数组时,我遇到了一些意外行为。

我尝试使用三个不同版本的数据库服务器( 2.2.22.2.3_rc02.2.3_rc1 )尽可能系统地对此进行测试。我将 MongoDB 的错误日志和我的平台信息等详细信息放在最后。

如果有人可以验证这种行为和/或告诉我我做错了什么,那就太好了。

示例文档

假设我们的数据库中有以下文档

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

我想更新第一个数组值(索引 = 0)。似乎这仅在新值与先前值没有“太大”差异的情况下才有效:

更新 1

成功

通过“第一个匹配运算符”()将值更改value1VALUE1数组array$

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

失败

但是,当我尝试更改VALUE1othervalue时,更新失败

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

更新 2

成功

通过位置索引将值更改VALUE1value1数组array

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

失败

同样,当我尝试将第一个数组值更改为 时abcd,更新失败

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的错误日志

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

平台信息

操作系统:Windows 7(64 位)

> 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

仅供感兴趣的人参考:这是生成示例文档的代码

#-------------------------------------------------------------------------------
# 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 的一位专家可以查看此问题。只需在此处引用它们。你已经很好地解释了情况。谢谢。

于 2013-01-28T17:17:07.920 回答