【问题标题】:Find Documents in MongoDB whose with an array field is a subset of a query array在 MongoDB 中查找具有数组字段的文档是查询数组的子集
【发布时间】:2015-06-18 05:26:04
【问题描述】:

假设我有一个插入一组文档,每个文档都有一个array 字段。我想找到所有文档,使得它们的 array 字段是查询数组的子集。例如,如果我有以下文件,

collection.insert([
  {
     'name': 'one',
     'array': ['a', 'b', 'c']
  },
  {
     'name': 'two',
     'array': ['b', 'c', 'd']
  },
  {
     'name': 'three',
     'array': ['b', 'c']
  }
])

并且我查询collection.find({'array': {'$superset': ['a', 'b', 'c']}),我希望看到文档onethree 因为['a', 'b', 'c']['b', 'c'] 都是['a', 'b', 'c'] 的子集。换句话说,我想做 Mongo 的 $all 查询的逆操作,它选择所有文档,使得查询数组是文档的 array 字段的子集。这可能吗?如果有,怎么做?

【问题讨论】:

  • 恕我直言,您需要做一些聚合。

标签: mongodb


【解决方案1】:

在 MongoDb 中,对于数组字段:

"$in:[...]" means "intersection" or "any element in",
"$all:[...]" means "subset" or "contain",
"$elemMatch:{...}" means "any element match"
"$not:{$elemMatch:{$nin:[...]}}" means "superset" or "in"

【讨论】:

    【解决方案2】:

    使用聚合框架或查找查询有一种简单的方法。

    查找查询很简单,但必须使用 $elemMatch 运算符:

    > db.collection.find({array:{$not:{$elemMatch:{$nin:['a','b','c']}}}}, {_id:0,name:1})
    

    请注意,这表示我们不想匹配具有(同时)不等于'a'、'b'或'c'的元素的数组。我添加了一个投影,它只返回结果文档的名称字段,这是可选的。

    【讨论】:

      【解决方案3】:

      要在聚合上下文中执行此操作,您可以使用$setIsSubset

      db.collection.aggregate([
          // Project the original doc and a new field that indicates if array
          // is a subset of ['a', 'b', 'c']
          {$project: {
              doc: '$$ROOT',
              isSubset: {$setIsSubset: ['$array', ['a', 'b', 'c']]}
          }},
          // Filter on isSubset
          {$match: {isSubset: true}},
          // Project just the original docs
          {$project: {_id: 0, doc: 1}}
      ])
      

      注意 $setIsSubset 是在 MongoDB 2.6 中添加的。

      【讨论】:

      • 不错的一个。我从我的答案中删除了旧的低效聚合,因为它更加优雅,现在已经有一段时间了。
      猜你喜欢
      • 2015-09-02
      • 1970-01-01
      • 1970-01-01
      • 2014-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-29
      • 1970-01-01
      相关资源
      最近更新 更多