【问题标题】:Mongodb: find documents with array where all elements exist in query array, but document array can be smallerMongodb:查找具有数组的文档,其中所有元素都存在于查询数组中,但文档数组可以更小
【发布时间】:2014-06-18 18:13:13
【问题描述】:

我的数据库中有一个集合,其中大多数文档都有一个数组字段。这些数组包含正好 2 个元素。现在我想找到所有这些数组元素都是我的查询数组元素的所有文档。

示例文档:

{ a:["1","2"] },
{ a:["2","3"] },
{ a:["1","3"] },
{ a:["1","4"] }

查询数组:

["1","2","3"]

查询应该找到前 3 个文档,但不是最后一个,因为我的查询数组中没有“4”。

预期结果:

{ a:["1","2"] },
{ a:["2","3"] },
{ a:["1","3"] }

期待一个有用的答案:)。

【问题讨论】:

    标签: arrays node.js mongodb nosql-aggregation


    【解决方案1】:

    由于大小是静态的,您只需检查两个元素是否都在 [1,2,3] 中;

    db.test.find(
      { $and: [ { "a.0": {$in: ["1","2","3"] } },
                { "a.1": {$in: ["1","2","3"] } } ] },
      { _id: 0, a: 1 }
    )
    
    >>> { "a" : [ "1", "2" ] }
    >>> { "a" : [ "2", "3" ] }
    >>> { "a" : [ "1", "3" ] }
    

    编辑:动态做有点麻烦,我想不出没有聚合框架的方法。只需将匹配计为 0,将不匹配计为 1,最后删除所有总和为 != 0;

    db.test.aggregate(
      { $unwind: "$a" },
      { $group: { _id: "$_id", 
                  a: { $push: "$a" },
                  fail: { $sum: {$cond: { if: { $or: [ { $eq:["$a", "1"] },
                                                       { $eq:["$a", "2"] },
                                                       { $eq:["$a", "3"] }]
                                              },
                                          then: 0,
                                          else: 1 } } } } },
      { $match: { fail: 0 } },
      { $project:{ _id: 0, a: 1 } } 
    )
    
    >>> { "a" : [ "1", "3" ] }
    >>> { "a" : [ "2", "3" ] }
    >>> { "a" : [ "1", "2" ] }
    

    【讨论】:

    • 非常好。这对我有用,我接受了它作为答案。如果有人找到一种非静态的方式,那就更好了。
    【解决方案2】:

    我还认为,没有聚合框架是不可能的(如果元素计数是动态的)。 但我发现了更通用的方法:

    db.tests.aggregate({
      $redact: {
        $cond: {
          if: {$eq: [ {$setIsSubset: [ '$a', [ "1", "2", "3" ] ]}]},
          then: '$$KEEP',
          else: '$$PRUNE'
        }
      }
    })
    

    【讨论】:

      【解决方案3】:

      我相信你的问题的答案是使用

      $in

      (来自文档:)

      考虑以下示例:

      db.inventory.find( { 数量: { $in: [ 5, 15 ] } } )

      此查询选择清单集合中 qty 字段值为 5 或 15 的所有文档。虽然您可以使用 $or 运算符表达此查询,但在执行相等检查时选择 $in 运算符而不是 $or 运算符在同一个领域。

      您还可以使用数组来做更复杂的事情。查看: http://docs.mongodb.org/manual/reference/operator/query/in/

      【讨论】:

      • 这也会在数组中找到最后一个包含“4”的文档,因为它与“1”匹配。如果文档包含一个不在查询数组中的元素,我希望它被过滤掉。
      • 我很快就意识到了这一点,并开始使用 $and 和 $where 来解决这个问题,但 Joachim 已经用一个可行的解决方案解决了这个问题:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-21
      • 1970-01-01
      • 1970-01-01
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      • 2014-12-11
      相关资源
      最近更新 更多