简体   繁体   English

在MongoDB(rmongodb)中使用$ set运算符更新数组

[英]Updating arrays with the $set operator in MongoDB (rmongodb)

I'm experiencing some unexpected behavior with respect to using the $set ( doc1 , doc2 ) operator to update arrays in MongoDB via rmongodb . 关于使用$setdoc1doc2 )运算符通过rmongodb更新MongoDB中的数组,我遇到了一些意外行为。

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 ). 我试图测试这个系统为尽可能与三个不同版本的数据库服务器(的2.2.22.2.3_rc02.2.3_rc1 )。 I put details such as MongoDB's error log and my Platform Infos at the very end. 我在最后放置了诸如MongoDB的错误日志和我的平台信息之类的详细信息。

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 ). 我想更新第一个数组值(index = 0 )。 It seems as if this only works if the new value does not differ "too much" from the previous value: 似乎这仅在新值与先前值没有太大差异时才起作用:

Update 1 更新1

Success 成功

Change value value1 to VALUE1 in array array via "first match operator" ( $ ) 通过“第一个匹配运算符”( $ )将数组array value1更改为VALUE1

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 但是,当我尝试将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

Update 2 更新2

Success 成功

Change value VALUE1 to value1 in array array via position index 通过位置索引将数组arrayVALUE1更改为value1

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 同样,当我尝试将第一个数组值更改为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's error log 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

Platform Infos 平台信息

OS: Windows 7 (64 Bit) 作业系统: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 ----------

Rappster, you are not having an 'R' problem nor an 'rmongodb' problem. Rappster,您没有遇到“ R”问题或“ rmongodb”问题。 Unfortunately, the server (mongod.exe) is messing up again. 不幸的是,服务器(mongod.exe)再次混乱了。 However, I tried this myself on mongod 2.2.2 (64-bit) and had no problem. 但是,我自己在mongod 2.2.2(64位)上进行了尝试,没有问题。 I looked at the code where the assertion is failing and couldn't see why it would fail unless a poorly formed BSON was being passed around or there's memory corruption from somewhere. 我查看了断言失败的代码,无法知道为什么失败,除非传递格式不正确的BSON或某处内存损坏。 It looks like another bug report needs to be filed so one of 10gen's experts can take a look at this. 看来还需要提交另一个错误报告,以便10gen的专家之一可以对此进行研究。 Just refer them here. 请在这里参考。 You have already explained the situation well. 您已经很好地说明了这种情况。 Thanks. 谢谢。

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

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