Mongodb比较对象数组键

时间:2015-12-29 15:30:39

标签: mongodb mongodb-query aggregation-framework

我在mongodb集合中保存了以下示例文档:

   {
       _id:"3213dsadsa812321",
       files: [ 
       {_id: "99300", path:"C:\Filename01.txt"},
       {_id: "99301", path:"C:\Filename02.txt"},
       {_id: "99302", path:"C:\Filename03.txt"},
       {_id: "99303", path:"C:\Filename04.txt"},
       ]
   }

我有以下数组var dynFiles:

  [          
       {_id: "1", path:"C:\folder\textfile01.txt"},
       {_id: "2", path:"C:\folder\textfile02.txt"},
       {_id: "3", path:"C:\folder\textfile03.txt"},
       {_id: "4", path:"C:\Filename04.txt"},
  ]

是否可以找到任何mongodb文档对象数组路径键是否与任何dynFiles var路径键匹配?

换句话说,基于给定的上述记录_id:db中的“99303”应该返回,因为它与var对象数组_id匹配:“4”。

预期结果:

[ {_id: "99303", path:"C:\Filename04.txt"} ]

经过广泛的研究后,我编写了以下查询,但不幸的是,它将文档files.path键与特定的对象数组键进行比较并没有多大帮助,而我需要它将files.path与dynFiles的所有路径进行比较。提前感谢您的帮助和时间

{ 'files.path': {$eq: dynFiles.path} }

2 个答案:

答案 0 :(得分:0)

您需要另一个仅包含映射路径的数组,这可以使用JavaScript的 .map() 方法派生。然后,此数组将在mongo查询中用作 $in 运算符值。以下内容证明了这一点:

var dynFiles = [          
       {_id: "1", path:"C:\folder\textfile01.txt"},
       {_id: "2", path:"C:\folder\textfile02.txt"},
       {_id: "3", path:"C:\folder\textfile03.txt"},
       {_id: "4", path:"C:\Filename04.txt"},
    ],
    paths = dynFiles.map(function(f){ return f.path; });

db.collection.find({"files.path": {"$in": paths }})

答案 1 :(得分:0)

使用.aggregate()方法。

首先,您需要使用.map()方法返回“path”数组。

*(*c + 2)

然后是聚合查询:

您只需要管道中的一个阶段,即$project阶段,您可以使用$map运算符返回“path”在“dynFiles”中的子文档数组。要检查给定的“路径”是否在“dynFiles”中,请使用$setIsSubset表达式中的$cond运算符。您需要> var dynFiles = [ ... {_id: "1", path:"C:\folder\textfile01.txt"}, ... {_id: "2", path:"C:\folder\textfile02.txt"}, ... {_id: "3", path:"C:\folder\textfile03.txt"}, ... {_id: "4", path:"C:\Filename04.txt"}, ... ]; > var paths = dynFiles.map(function(element) { ... return element.path; ... }); > paths [ "C:\folder\textfile01.txt", "C:\folder\textfile02.txt", "C:\folder\textfile03.txt", "C:Filename04.txt" ] 的原因是您无法在$setIsSubset表达式中使用$in运算符。当然$cond运算符需要两个数组作为参数,您需要使用$setIsSubset运算符来返回一个元素数组。当然,$literal运算符允许您将文字数组分配给$map中的“输入”。此外,您需要使用此处的$setDifference来过滤掉数组中的所有$map,只要被过滤的数据是“唯一的”,就可以。

false

另一种方式,也许最简单的方法是在MongoDB 3.2中使用$filter运算符new

db.paths.aggregate([
    { "$project": { 
        "files": { 
            "$setDifference": [
                { "$map": { 
                    "input": "$files", 
                    "as": "file", 
                    "in": { 
                        "$cond": [ 
                            { "$setIsSubset": [ 
                                { "$map": {
                                    "input": { "$literal": [ "A" ] },
                                    "as": "el", 
                                    "in": "$$file.path"
                                }}, 
                                paths
                            ] },
                            "$$file",
                            false 
                        ]
                    }
                }}, 
                [false]
            ]
        }
    }}
])

两个查询都会产生相同的结果:

db.paths.aggregate([
    { "$project": { 
        "files": {
            "$filter": { 
                "input": "$files", 
                "as": "file",  
                "cond": {
                    "$setIsSubset": [
                        { "$map": {
                            "input": { "$literal": [ "A" ] }, 
                            "as": "el", 
                            "in": "$$file.path"
                        }}, 
                        paths 
                    ]
                }
            }
        }
    }}
])