这个问题与this one密切相关,我会考虑在NoSQL上下文中给出关于模式设计的建议,但我很想知道这个:
实际问题
假设您有以下文档:
_id : 2 abcd
name : 2 unittest.com
paths : 4
0 : 3
path : 2 home
queries : 4
0 : 3
name : 2 query1
url : 2 www.unittest.com/home?query1
requests: 4
1 : 3
name : 2 query2
url : 2 www.unittest.com/home?query2
requests: 4
基本上,我想知道
- 如果可以多次使用MongoDB的位置
$
运算符(details),或者换句话说,在涉及"degree of nestedness"大于1的数组/文档结构的更新方案中:
{ <update operator>: { "paths.$.queries.$.requests" : value } }
( doesn't work )
而不是"only"能够使用 $
once 作为顶级数组并绑定为"higher levels"上的数组使用显式索引:
{ <update operator>: { "paths.$.queries.0.requests" : value } }
)( works )
- 如果可能的话,相应的R语法将如何 .
您将在下面找到一个可重复的示例 . 我试着尽量简洁 .
代码示例
数据库连接
require("rmongodb")
db <- "__unittest"
ns <- paste(db, "hosts", sep=".")
# CONNCETION OBJECT
con <- mongo.create(db=db)
# ENSURE EMPTY DB
mongo.remove(mongo=con, ns=ns)
示例文档
q <- list("_id"="abcd")
b <- list("_id"="abcd", name="unittest.com")
mongo.insert(mongo=con, ns=ns, b=b)
q <- list("_id"="abcd")
b <- list("$push"=list(paths=list(path="home")))
mongo.update(mongo=con, ns, criteria=q, objNew=b)
q <- list("_id"="abcd", paths.path="home")
b <- list("$push"=list("paths.$.queries"=list(
name="query1", url="www.unittest.com/home?query1")))
mongo.update(mongo=con, ns, criteria=q, objNew=b)
b <- list("$push"=list("paths.$.queries"=list(
name="query2", url="www.unittest.com/home?query2")))
mongo.update(mongo=con, ns, criteria=q, objNew=b)
使用显式位置索引更新嵌套数组(有效)
这有效,但它涉及到第二级数组的 explicit 索引 queries
(嵌套在数组 paths
的子文件元素中):
q <- list("_id"="abcd", paths.path="home", paths.queries.name="query1")
b <- list("$push"=list("paths.$.queries.0.requests"=list(time="2013-02-13")))
> mongo.bson.from.list(b)
$push : 3
paths.$.queries.0.requests : 3
time : 2 2013-02-13
mongo.update(mongo=con, ns, criteria=q, objNew=b)
res <- mongo.find.one(mongo=con, ns=ns, query=q)
> res
_id : 2 abcd
name : 2 unittest.com
paths : 4
0 : 3
path : 2 home
queries : 4
0 : 3
name : 2 query1
requests : 4
0 : 3
time : 2 2013-02-13
url : 2 www.unittest.com/home?query1
1 : 3
name : 2 query2
url : 2 www.unittest.com/home?query2
使用位置$索引更新嵌套数组(不起作用)
现在,我想用显式 0
替换位置 $
运算符,就像我一样,让服务器找到所需的数组 paths
( paths.$.queries
)的subdoc元素 .
AFAIU documentation,这应该起作用,因为关键是指定一个"correct"查询选择器:
位置$运算符,当与update()方法一起使用时,充当更新查询选择器的第一个匹配项的占位符:
我想我指定了一个查询选择器 does 找到正确的嵌套元素(由于 paths.queries.name="query1"
部分):
q <- list("_id"="abcd", paths.path="home", paths.queries.name="query1")
我想翻译成“普通的MongoDB”语法,查询选择器看起来有点像这样
{ _id: abcd, paths.path: home, paths.queries.name: query1 }
这对我来说似乎是一个有效的查询选择器 . 实际上它确实匹配了所需的元素/ doc:
> !is.null(mongo.find.one(mongo=con, ns=ns, query=q))
[1] TRUE
我的想法是,如果它在顶级工作,为什么它不适用于更高级别(只要查询选择器指向正确的嵌套组件)?
但是,服务器似乎不喜欢嵌套或多次使用 $
:
b <- list("$push"=list("paths.$.queries.$.requests"=list(time="2013-02-14")))
> mongo.bson.from.list(b)
$push : 3
paths.$.queries.$.requests : 3
time : 2 2013-02-14
> mongo.update(mongo=con, ns, criteria=q, objNew=b)
[1] FALSE
我不确定它是否不起作用,因为MongoDB不支持这个或者我没有得到R语法 .
2 回答
位置运算符仅支持一级深度,仅支持第一个匹配元素 .
有一个JIRA可跟踪您想要的行为:https://jira.mongodb.org/browse/SERVER-831
我不确定它是否允许不止一场比赛,但我相信这将是由于它将如何运作的动态 .
如果您可以从MongoDB shell执行查询,可以通过利用MongoDB游标的 forEach 函数(http://docs.mongodb.org/manual/reference/method/cursor.forEach/)来绕过此限制
以下是3个嵌套数组的示例:
请注意,这更像是一次性解决方案,而不是 生产环境 代码,但如果您必须编写修复脚本,它将会完成工作 .