$set
在使用( doc1 , doc2 ) 运算符通过rmongodb更新MongoDB中的数组时,我遇到了一些意外行为。
我尝试使用三个不同版本的数据库服务器( 2.2.2、2.2.3_rc0和2.2.3_rc1 )尽可能系统地对此进行测试。我将 MongoDB 的错误日志和我的平台信息等详细信息放在最后。
如果有人可以验证这种行为和/或告诉我我做错了什么,那就太好了。
示例文档
假设我们的数据库中有以下文档
_id : 7 5106887fe2be1937c1e3c8b0
host : 2 host1.com
array : 4
0 : 2 value1
1 : 2 value2
2 : 2 value3
我想更新第一个数组值(索引 = 0
)。似乎这仅在新值与先前值没有“太大”差异的情况下才有效:
更新 1
成功
通过“第一个匹配运算符”()将值更改value1
为VALUE1
数组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
失败
但是,当我尝试更改VALUE1
为othervalue
时,更新失败
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
成功
通过位置索引将值更改VALUE1
为value1
数组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 ----------