2015-12-29 88 views
1

我有以下的樣本文檔保存在我的MongoDB集合: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 path key?

換句話說,基於上面給出的記錄_id:db中的「99303」應該返回,因爲它與var對象數組_id:「4」匹配。

預期結果:

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

廣泛的研究之後,我寫了下面的查詢,但遺憾的是它沒有太大的幫助,因爲它與特定對象數組鍵比較文檔files.path鍵,而我需要它將files.path與dynFiles的所有路徑進行比較。在此先感謝您的幫助和時間

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

回答

0

您將需要一個僅包含映射路徑,這可以使用JavaScript的.map()方法推導出另一個數組。然後這個數組將在mongo查詢中用作運算符值。以下演示如下:

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 }}) 
+0

這不起作用! – styvane

0

使用.aggregate()方法。

首先,您需要使用.map()方法返回「路徑」數組。

> 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" 
] 

然後是聚集查詢:

,您只需要在您的管道一期也就是$project階段,你使用$map操作返回子文檔的數組,其中「路徑」是在「dynFiles」中。要檢查給定的「路徑」是否在「dynFiles」中,請在$cond表達式中使用$setIsSubset運算符。您需要$setIsSubset的原因是因爲您無法在$cond表達式中使用$in運算符。當然,$setIsSubset運算符需要兩個數組作爲參數,您需要使用$map運算符返回一個元素數組。當然,$literal運算符可讓您將一個文字數組分配給$map中的「輸入」。此外,您需要在這裏使用$setDifference從數組中篩選出所有的false,只要被過濾的數據是「唯一的」即可。

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] 
      ] 
     } 
    }} 
]) 

另一種方式,也許最簡單的方法是使用$filter操作MongoDB中3個新的。2個

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

兩個查詢產生相同的結果:

{ 
     "_id" : "3213dsadsa812321", 
     "files" : [ 
       { 
         "_id" : "99303", 
         "path" : "C:Filename04.txt" 
       } 
     ] 
}