比较数组并返回差异

Haw*_*ngs 2 mongodb mongodb-query aggregation-framework

我在运行时创建的内存中有一个数组A,另一个数组B保存在mongo数据库中.如何有效地从A中获取不在B中的所有元素?

您可以假设存储在mongodb中的数组比运行时创建的数组大几个数量级,因此我认为从mongo获取完整数组并计算结果效率不高,但我没有找到任何查询在mongo中操作,允许我计算我想要的结果.

请注意,$ nin运算符与我想要的相反,即它从B中检索不在A中的元素.

例:

在运行时在我的应用程序中创建的数组A是[2, 3, 4].

存储在mongodb中的数组B是[1, 3, 5, 6, 7, 10].

我期望的结果是[2, 4].

Nei*_*unn 6

唯一的事情反应即"修改"的文件是.aggregate().mapReduce(),其中前者是更好的选择.

在这种情况下,您要求$setDifference比较"集合"并返回两者之间的"差异".

所以用你的数组表示一个文档:

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

运行聚合:

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

哪个回报:

{ "_id" : ObjectId("596005eace45be96e2cb221b"), "c" : [ 2, 4 ] }
Run Code Online (Sandbox Code Playgroud)

如果你不想要的"套",而是要提供一个数组一样[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" ]  }
        }
      }
    }   
  }}
])
Run Code Online (Sandbox Code Playgroud)

$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" ]    
                }
              }    
            }
          }
        }    
      }
    }    
  }}
])
Run Code Online (Sandbox Code Playgroud)

两者都会返回:

{ "_id" : ObjectId("596005eace45be96e2cb221b"), "c" : [ 2, 4, 4 ] }
Run Code Online (Sandbox Code Playgroud)

这当然是"不是一组",因为它4被作为输入"两次"提供,因此也返回"两次".