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

MongoDB中如何对嵌套数组内的元素按顺序两两配对?

MongoDB 数组相邻元素两两配对实现方案

直接使用MongoDB聚合管道即可完成需求,不需要应用层额外处理,完整查询语句如下:

db.your_collection.aggregate([
  {
    $project: {
      events: {
        $map: {
          input: { $range: [0, { $size: "$events" }] },
          as: "idx",
          in: {
            $mergeObjects: [
              { $arrayElemAt: ["$events", "$$idx"] },
              {
                mod: { $mod: ["$$idx", 2] },
                pairIndex: { $floor: { $divide: ["$$idx", 2] } }
              }
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      couples: {
        $reduce: {
          input: "$events",
          initialValue: [],
          in: {
            $let: {
              vars: {
                currentPair: { $arrayElemAt: ["$$value", "$$this.pairIndex"] }
              },
              in: {
                $cond: [
                  { $isArray: "$$currentPair" },
                  {
                    $concatArrays: [
                      { $slice: ["$$value", "$$this.pairIndex"] },
                      [{ $concatArrays: ["$$currentPair", ["$$this"]] }],
                      { $slice: ["$$value", { $add: ["$$this.pairIndex", 1] }, { $size: "$$value" }] }
                    ]
                  },
                  { $concatArrays: ["$$value", [["$$this"]]] }
                ]
              }
            }
          }
        }
      }
    }
  }
])

逻辑说明

  • 第一阶段通过$range生成与events数组等长的从0开始的索引序列,遍历每个索引时取出对应位置的事件对象,追加两个标记字段:mod为索引对2取余的结果(每对第一个元素值为0,第二个为1,和需求输出一致),pairIndex为索引除以2向下取整的结果,用来标记当前元素所属的配对组。
  • 第二阶段通过$reduce遍历带标记的事件列表,遍历过程中按pairIndex归组:如果对应位置的配对数组已存在,就将当前元素追加到该配对数组中;如果不存在,就新建一个包含当前元素的配对数组放到对应位置,最终输出的couples字段就是符合要求的二维配对数组。
  • 该方案为通用实现,支持任意长度的输入数组:如果数组长度为奇数,最后一个配对组只会包含单个元素,可根据业务需求在管道末尾追加$project阶段过滤掉长度不足2的配对组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:45:30