多次使用的位置`$`运营商的更新嵌套的数组(Multiple use of the position

2019-07-19 20:29发布

这个问题是密切相关的这一个 ,我会考虑在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

基本上,我想知道

  1. 如果可以使用MongoDB的位置$运营商( 详细信息 )多次,或者换句话说,在涉及阵列/文档结构具有大于1“的嵌套结构的程度”更新方案:

    { <update operator>: { "paths.$.queries.$.requests" : value } } 不工作

    而不是“唯一”能够使用$一个顶级阵列一次被绑定到使用显式索引的“更高级别”的阵列:

    { <update operator>: { "paths.$.queries.0.requests" : value } } 作品

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

有明确的位置索引嵌套数组的更新(作品)

这工作,但它涉及到用于第二级阵列的显式索引queries (嵌套成阵列的subdoc的元件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与位置$就像我为了让服务器找到的阵列所需的subdoc的元素做操作pathspaths.$.queries )。

AFAIU的文档 ,这应该工作作为关键的是要指定一个“正确”的查询选择:

的位置$操作者,与该更新()方法中使用,并且当用作用于更新查询选择器的第一个匹配的占位符:

我想我指定的查询选择, 找到正确的嵌套元素(由于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语法正确。

Answer 1:

位置操作者只支持一个水平深,并且只有第一匹配元件。

还有就是你想在这里一个JIRA可追踪的那种行为: https://jira.mongodb.org/browse/SERVER-831

我不确定它是否会允许一个以上的比赛,但我相信它会因它需要怎样的工作动态。



Answer 2:

如果你可以从MongoDB的执行查询外壳就可以绕过这个限制,通过利用MongoDB的光标的forEach功能( http://docs.mongodb.org/manual/reference/method/cursor.forEach/ )

这里是用3个嵌套阵列的示例:

var collectionNameCursor = db.collection_name.find({...});

collectionNameCursor.forEach(function(collectionDocument) {
    var firstArray = collectionDocument.firstArray;
    for(var i = 0; i < firstArray.length; i++) {
        var secondArray = firstArray[i].secondArray;
        for(var j = 0; j < secondArray.length; j++) {
            var thirdArray = secondArray[j].thirdArray;
            for(var k = 0; k < thirdArray.length; k++) {
                //... do some logic here with thirdArray's elements
                db.collection_name.save(collectionDocument);
            }
        }
    }
});

请注意,这更多的是一个时间的解决方案,然后生产代码,但它会做的工作,如果你有写FIX-up脚本。



文章来源: Multiple use of the positional `$` operator to update nested arrays