多次使用位置 `$` 运算符来更新嵌套数组 [英] Multiple use of the positional `$` operator to update nested arrays

查看:19
本文介绍了多次使用位置 `$` 运算符来更新嵌套数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与这个问题密切相关,我会考虑给出的建议关于 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

基本上,我想知道

  1. 是否可以使用 MongoDB 的位置 $ 运算符 (details) 多次,或者换种说法,在涉及嵌套度"大于 1 的数组/文档结构的更新场景中:

    { : { "paths.$.queries.$.requests" : value } }(不起作用)

    而不是仅"能够对顶级数组使用$ 一次,并且必须对更高级别"的数组使用显式索引:

    { : { "paths.$.queries.0.requests" : value } }) (有效)

  2. 如果可能的话,相应的 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

  1. 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)

  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆