多次使用位置 `$` 运算符来更新嵌套数组 [英] Multiple use of the positional `$` operator to update nested arrays
问题描述
这个问题与这个问题密切相关,我会考虑给出的建议关于 NoSQL 上下文中的架构设计,但我很想了解这一点:
实际问题
假设您有以下文档:
_id : 2 abcd名称:2 unittest.com路径:40 : 3路径 : 2 家查询 : 40 : 3名称 : 2 query1网址:2 www.unittest.com/home?query1要求:41 : 3名称 : 2 query2网址:2 www.unittest.com/home?query2要求:4
基本上,我想知道
是否可以使用 MongoDB 的位置
$
运算符 (details) 多次,或者换种说法,在涉及嵌套度"大于 1 的数组/文档结构的更新场景中:{
(不起作用): { "paths.$.queries.$.requests" : value } } 而不是仅"能够对顶级数组使用
$
一次,并且必须对更高级别"的数组使用显式索引:
莉>{
) (有效): { "paths.$.queries.0.requests" : value } } 如果可能的话,相应的 R 语法会是什么样子.
您会在下面找到一个可重现的示例.我尽量简洁.
<小时>代码示例
数据库连接
require("rmongodb")db <- "__unittest"ns <- paste(db, "hosts", sep=".")# 连接对象con <- mongo.create(db=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,标准=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,标准=q,objNew=b)b <- list("$push"=list("paths.$.queries"=list(name="query2", url="www.unittest.com/home?query2")))mongo.update(mongo=con,ns,标准=q,objNew=b)
使用显式位置索引更新嵌套数组(有效)
这有效,但它涉及二级数组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)$推:3路径.$.queries.0.requests : 3时间 : 2 2013-02-13mongo.update(mongo=con,ns,标准=q,objNew=b)res <- mongo.find.one(mongo=con, ns=ns, query=q)>资源_id : 2 abcd名称:2 unittest.com路径:40 : 3路径 : 2 家查询 : 40 : 3名称 : 2 query1要求:40 : 3时间 : 2 2013-02-13网址:2 www.unittest.com/home?query11 : 3名称 : 2 query2网址:2 www.unittest.com/home?query2
使用位置 $
索引更新嵌套数组(不起作用)
现在,我想将显式 0
替换为位置 $
运算符,就像我所做的那样,以便让服务器找到所需的数组子文档元素paths
(paths.$.queries
).
AFAIU 文档,这应该是关键事情是指定一个正确"的查询选择器:
<块引用><块引用>位置 $ 运算符,当与 update() 方法一起使用时,充当更新查询选择器的第一个匹配项的占位符:
我想我指定了一个查询选择器,它确实找到了正确的嵌套元素(由于 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}
对我来说这似乎是一个有效的查询选择器.事实上,它确实匹配所需的元素/文档:
>!is.null(mongo.find.one(mongo=con, ns=ns, 查询=q))[1] 真
我的想法是,如果它适用于顶级,为什么它不能适用于更高级别(只要查询选择器指向正确的嵌套组件)?
然而,服务器似乎不喜欢 $
的嵌套或多次使用:
b <- list("$push"=list("paths.$.queries.$.requests"=list(time="2013-02-14")))>mongo.bson.from.list(b)$推:3路径.$.queries.$.requests : 3时间 : 2 2013-02-14>mongo.update(mongo=con,ns,标准=q,objNew=b)[1] 错误
我不确定它是否不起作用,因为 MongoDB 不支持此功能,或者我没有正确使用 R 语法.
位置运算符仅支持一层深度且仅支持第一个匹配元素.
有一个 JIRA 可跟踪您想要的行为类型:https://jira.mongodb.org/browse/SERVER-831
我不确定它是否会允许不止一场比赛,但我相信这是由于它需要如何工作的动态变化.
This question is closely related to this one and I will consider the advice given with respect to schema design in a NoSQL context, yet I'm curious to understand this:
Actual questions
Suppose you have the following document:
_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
Basically, I'd like to know
if it is possible to use MongoDB's positional
$
operator (details) multiple times, or put differently, in update scenarios that involve array/document structures with a "degree of nestedness" greater than 1:{ <update operator>: { "paths.$.queries.$.requests" : value } }
(doesn't work)instead of "only" be able to use
$
once for a top-level array and being bound to use explicit indexes for arrays on "higher levels":{ <update operator>: { "paths.$.queries.0.requests" : value } }
) (works)if possible at all, how the corresponding R syntax would look like.
Below you'll find a reproducible example. I tried to be as concise as possible.
Code example
Database connection
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)
Example document
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)
Update of nested arrays with explicit position index (works)
This works, but it involves an explicit index for the second-level array queries
(nested in a subdoc element of array 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
Update of nested arrays with positional $
indexes (doesn't work)
Now, I'd like to substitute the explicit 0
with the positional $
operator just like I did in order to have the server find the desired subdoc element of array paths
(paths.$.queries
).
AFAIU the documentation, this should work as the crucial thing is to specify a "correct" query selector:
The positional $ operator, when used with the update() method and acts as a placeholder for the first match of the update query selector:
I think I specified a query selector that does find the correct nested element (due to the paths.queries.name="query1"
part):
q <- list("_id"="abcd", paths.path="home", paths.queries.name="query1")
I guess translated to "plain MongoDB" syntax, the query selector looks somewhat like this
{ _id: abcd, paths.path: home, paths.queries.name: query1 }
which seems like a valid query selector to me. In fact it does match the desired element/doc:
> !is.null(mongo.find.one(mongo=con, ns=ns, query=q))
[1] TRUE
My thought was that if it works on the top-level, why shouldn't it work for higher levels as well (as long as the query selector points to the right nested components)?
However, the server doesn't seem to like a nested or multiple use of $
:
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
I'm not sure if it doesn't work because MongoDB doesn't support this or if I didn't get the R syntax right.
The positional operator only supports one level deep and only the first matching element.
There is a JIRA trackable for the sort of behaviour you want here: https://jira.mongodb.org/browse/SERVER-831
I am unsure if it will allow for more than one match but I believe it will due to the dynamics of how it will need to work.
这篇关于多次使用位置 `$` 运算符来更新嵌套数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!