使用 MongoDB 过滤器计算两个数组之间匹配元素的数量

问题描述 投票:0回答:2

我需要使用 MongoDB 过滤器聚合来计算 2 个数组之间匹配元素的数量。我尝试在过滤器的条件字段上使用 $eq 和 $setIntersection,但即使所有 4 个元素都匹配,匹配元素的数量也仅返回 1

用户场景如下:

  1. 用户输入4位数字:1,2,3,4
  2. 它应该检查它与后端数字的匹配数量。在这种情况下,还有 1, 2, 3, 4
  3. 应返回 4 匹配项。

现在,它在我的查询中只返回 1。如果存在不匹配,例如用户输入 1, 2, 3, 5 那么它应该返回 3 匹配。

这是查询:

db.collection.aggregate({
  $match: {
    "entries.numbers": {
      $in: [
        1,
        2,
        3,
        4
      ]
    }
  }
},
{
  "$addFields": {
    "matchingCount": {
      $size: {
        $filter: {
          input: "$entries",
          as: "e",
          cond: {
            $eq: [
              "$$e.numbers",
              [
                1,
                2,
                3,
                4
              ]
            ]
          }
        }
      }
    }
  }
})

这是游乐场链接:https://mongoplayground.net/p/5YSDOL6LwGs

database mongodb nosql
2个回答
0
投票

1.Wrt

但即使 4 个元素全部匹配,匹配元素的数量也仅返回 1。

如果从

$size
阶段删除
$addFields
部分,您会看到
matchingCount
实际上是一个对象的列表,因此
$size
返回 1。

"matchingCount": [
  {
    "name": "Josh",
    "numbers": [ 1, 2, 3, 4 ]
  }
]

此外,在管道中的任何位置更改

[ 1, 2, 3, 4 ]
的顺序或根本不匹配。所以你真的应该只使用集合。

2.你的另一个问题中,你给出了一个示例db,其中所有其他

entries
都在一个文档中,作为对象数组。

因此,如果您想要所有具有 至少一个正确猜测的匹配条目:

输入集合,数字顺序与“中奖”不同

[1, 2, 3, 4]
:

[
  {
    "_id": "1234",
    "entries": [
      {"name": "Josh", "numbers": [4, 1, 3, 2]},
      {"name": "only three", "numbers": [1, 2, 3, 5]},
      {"name": "none", "numbers": [9, 8, 7, 6]}  // no matches
    ]
  }
]

查询:

db.collection.aggregate([
  { $unwind: "$entries" },
  {
    // separated for clarity
    $addFields: {
      intersect: {
        $setIntersection: [
          "$entries.numbers",
          [ 1, 2, 3, 4 ]
        ]
      }
    }
  },
  {
    // remove docs which have no match
    $match: {
      intersect: { $ne: [] }
    }
  },
  {
    // can be combined with the stage above
    $addFields: {
      matchingCount: { $size: "$intersect" }
    }
  },
  {
    // if you only want guesses with at least three matches
    $match: {
      $expr: {
        $gte: [
          // change this two whatever you want
          "$matchingCount",
          3
        ]
      }
    }
  },
  {
    $unset: [ "fields", "you", "don't", "want" ]
  }
])

我的示例数据库的结果:

[
  {
    "_id": "1234",
    "entries": { "name": "Josh", "numbers": [ 4, 1, 3, 2 ] },
    "intersect": [ 1, 2, 3, 4 ],
    "matchingCount": 4
  },
  {
    "_id": "1234",
    "entries": { "name": "only three", "numbers": [ 3, 5, 1, 2 ] },
    "intersect": [ 1, 2, 3 ],
    "matchingCount": 3
  }
]

蒙戈游乐场

这是一个组合阶段版本,以及 操场

db.collection.aggregate([
  { $unwind: "$entries" },
  {
    // can be combined with the stage above
    $addFields: {
      matchingCount: {
        $size: {
          $setIntersection: [
            "$entries.numbers",
            [ 1, 2, 3, 4 ]
          ]
        }
      }
    }
  },
  {
    // if you only want guesses with at least three matches
    $match: {
      $expr: {
        $gte: [
          // change this two whatever you want
          "$matchingCount",
          3
        ]
      }
    }
  }
])

0
投票

尝试这个查询:

 db.collection.aggregate([
  {
    $match: {
      "entries.numbers": { $in: [1, 2, 3, 4] }
    }
  },
  {
    $addFields: {
      matchingNumbers: {
        $setIntersection: ["$entries.numbers", [1, 2, 3, 4]]
      }
    }
  },
  {
    $addFields: {
      matchingCount: { $size: "$matchingNumbers" }
    }
  }
])
© www.soinside.com 2019 - 2024. All rights reserved.