You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB聚合操作中实现按位与运算的可行方案问询

解决方案:MongoDB聚合中实现按位与运算

好问题!确实MongoDB的$bit操作符仅支持文档更新场景,没法直接在聚合管道里执行按位运算,但从MongoDB 4.2版本开始,我们有了完美的解决方案——用聚合表达式原生支持的$bitAnd运算符来实现你要的按位与计算。

最优方案(MongoDB 4.2+)

我们可以通过聚合管道先获取目标文档(_id:1)的choices值,再对所有其他文档执行按位与运算,步骤如下:

完整聚合管道

db.collection.aggregate([
  // 1. 聚合所有文档,提取目标值并保存所有文档数据
  {
    $group: {
      _id: null,
      targetChoices: { $first: { $cond: [{ $eq: ["$_id", 1] }, "$choices", "$$REMOVE"] } },
      docs: { $push: "$$ROOT" }
    }
  },
  // 2. 展开文档数组,过滤掉目标文档本身(可选)
  { $unwind: "$docs" },
  { $match: { "docs._id": { $ne: 1 } } },
  // 3. 计算按位与结果,生成and_op字段
  {
    $project: {
      _id: "$docs._id",
      choices: "$docs.choices",
      and_op: { $bitAnd: ["$docs.choices", "$targetChoices"] }
    }
  },
  // 可选:按and_op降序排序,匹配你的示例输出顺序
  { $sort: { and_op: -1 } }
])

执行结果

针对你提供的示例数据,运行上述管道后会得到:

{ "_id" : 3, "choices" : 3, "and_op" : 3 }
{ "_id" : 2, "choices" : 5, "and_op" : 1 }
{ "_id" : 4, "choices" : 4, "and_op" : 0 }

简化版本(已知目标值时)

如果你已经提前查询到_id:1的choices值为3,可以直接把目标值写死,让管道更简洁高效:

db.collection.aggregate([
  { $match: { _id: { $ne: 1 } } },
  {
    $project: {
      choices: 1,
      and_op: { $bitAnd: ["$choices", 3] }
    }
  },
  { $sort: { and_op: -1 } }
])

兼容旧版本(MongoDB 4.2之前)

如果你的MongoDB版本低于4.2,没有原生的$bitAnd,可以通过自定义逻辑模拟按位与:遍历每一位判断是否在两个数中都为1,累加对应权重得到结果。

db.collection.aggregate([
  {
    $group: {
      _id: null,
      targetChoices: { $first: { $cond: [{ $eq: ["$_id", 1] }, "$choices", "$$REMOVE"] } },
      docs: { $push: "$$ROOT" }
    }
  },
  { $unwind: "$docs" },
  { $match: { "docs._id": { $ne: 1 } } },
  {
    $project: {
      _id: "$docs._id",
      choices: "$docs.choices",
      and_op: {
        $reduce: {
          input: { $range: [0, 32] }, // 针对32位整数遍历每一位
          initialValue: 0,
          in: {
            $add: [
              "$$value",
              {
                $cond: [
                  {
                    $and: [
                      { $ne: [{ $bitwiseAnd: ["$docs.choices", { $pow: [2, "$$this"] }] }, 0] },
                      { $ne: [{ $bitwiseAnd: ["$targetChoices", { $pow: [2, "$$this"] }] }, 0] }
                    ]
                  },
                  { $pow: [2, "$$this"] },
                  0
                ]
              }
            ]
          }
        }
      }
    }
  },
  { $sort: { and_op: -1 } }
])

额外补充:实现最初的“匹配比特位数量”需求

其实你最初想要的「统计相同比特位上1的匹配数量」也可以轻松实现,MongoDB 5.0+新增了$bitCount运算符,用来计算整数的二进制中1的个数。结合$bitAnd就能得到匹配数量:

db.collection.aggregate([
  { $match: { _id: { $ne: 1 } } },
  {
    $project: {
      choices: 1,
      and_op: { $bitAnd: ["$choices", 3] },
      matches: { $bitCount: { $bitAnd: ["$choices", 3] } }
    }
  },
  { $sort: { matches: -1 } }
])

执行后会得到你理想中的结果:

{ "_id" : 3, "choices" : 3, "and_op" : 3, "matches" : 2 }
{ "_id" : 2, "choices" : 5, "and_op" : 1, "matches" : 1 }
{ "_id" : 4, "choices" : 4, "and_op" : 0, "matches" : 0 }

内容的提问来源于stack exchange,提问作者Saran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 03:22:32