2017-07-07 101 views
1

我有一個在運行時創建的內存中的數組A和保存在mongo數據庫中的另一個數組B.我如何有效地獲得A中不在B中的所有元素?比較數組並返回差異

你可以假設存儲在mongodb中的數組比我在運行時創建的數組大幾個數量級,因此我認爲從mongo獲得完整數組並計算結果效率不高,但我有沒有在mongo中發現任何查詢操作,這讓我可以計算出我想要的結果。

注意,$nin運營商做的我想要的東西,也就是相反的,它檢索的B不在A.元素

例子:

數組,我在運行時創建機應用,是[2, 3, 4]

存儲在mongodb中的數組B是[1, 3, 5, 6, 7, 10]

我期望的結果是[2, 4]

回答

3

「修改」文檔的唯一要求是.aggregate().mapReduce(),其中前者是更好的選擇。

在這種情況下,您要求$setDifference比較「集合」並返回兩者之間的「差異」。

因此代表與您的陣列文檔:

db.collection.insert({ "b": [1, 3, 5, 6, 7, 10] }) 

運行聚集:

db.collection.aggregate([{ "$project": { "c": { "$setDifference": [ [2,3,4], "$b" ] } } }]) 

將返回:

{ "_id" : ObjectId("596005eace45be96e2cb221b"), "c" : [ 2, 4 ] } 

如果你不想要的 「套」,而是想要提供像[2,3,4,4]這樣的陣列,那麼你可以比較$filter$in相反,如果你有MongoDB的3.4至少:

db.collection.aggregate([ 
    { "$project": { 
    "c": { 
     "$filter": { 
     "input": [2,3,4,4], 
     "as": "a", 
     "cond": { 
      "$not": { "$in": [ "$$a", "$b" ] } 
     } 
     } 
    } 
    }} 
]) 

或用在早期版本$filter$anyElementTrue

db.collection.aggregate([ 
    { "$project": { 
    "c": { 
     "$filter": { 
     "input": [2,3,4,4], 
     "as": "a", 
     "cond": { 
      "$not": { 
      "$anyElementTrue": { 
       "$map": { 
       "input": "$b", 
       "as": "b", 
       "in": { 
        "$eq": [ "$$a", "$$b" ]  
       } 
       }  
      } 
      } 
     }  
     } 
    }  
    }} 
]) 

在哪裏都將返回:

{ "_id" : ObjectId("596005eace45be96e2cb221b"), "c" : [ 2, 4, 4 ] } 

這當然是「不是一組」,因爲4作爲輸入提供「兩次」,因此也返回「兩次」。