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

MongoDB中同数组/跨数组移动元素的实现方案求助

MongoDB 跨/同课时移动内容的通用查询语句

原始文档结构

{
  lessons: [
    {
      _id: 'lesson1',
      title: 'lesson1',
      contents: [
        {
          _id: 'content1',
          title: 'content1',
        },
        {
          _id: 'content2',
          title: 'content2',
        },
        {
          _id: 'content3',
          title: 'content3',
        }
      ]
    },
    {
      _id: 'lesson2',
      title: 'lesson2',
      contents: [
        {
          _id: 'content1',
          title: 'content1',
        },
        {
          _id: 'content2',
          title: 'content2',
        },
        {
          _id: 'content3',
          title: 'content3',
        }
      ]
    }
  ]
}

需求说明

已知originLessonId、targetLessonId(可与源ID相同)、contentId和目标位置index,需实现两种场景的内容移动:

  • 同课时内调整位置:将指定课时下的内容移至该课时内的目标索引位置
    请求参数示例:{ originLessonId: 'lesson1', targetLessonId: 'lesson1', contentId: 'content1', index: 2 }
    预期结果:
    {
      lessons: [
        {
          _id: 'lesson1',
          title: 'lesson1',
          contents: [
            { _id: 'content2', title: 'content2' },
            { _id: 'content3', title: 'content3' },
            { _id: 'content1', title: 'content1' }
          ]
        },
        {
          _id: 'lesson2',
          title: 'lesson2',
          contents: [
            { _id: 'content1', title: 'content1' },
            { _id: 'content2', title: 'content2' },
            { _id: 'content3', title: 'content3' }
          ]
        }
      ]
    }
    
  • 跨课时移动内容:将源课时下的内容移至目标课时的指定索引位置,同时从源课时中移除该内容
    请求参数示例:{ originLessonId: 'lesson1', targetLessonId: 'lesson2', contentId: 'content1', index: 1 }
    预期结果:
    {
      lessons: [
        {
          _id: 'lesson1',
          title: 'lesson1',
          contents: [
            { _id: 'content2', title: 'content2' },
            { _id: 'content3', title: 'content3' }
          ]
        },
        {
          _id: 'lesson2',
          title: 'lesson2',
          contents: [
            { _id: 'content1', title: 'content1' },
            { _id: 'content1', title: 'content1' },
            { _id: 'content2', title: 'content2' },
            { _id: 'content3', title: 'content3' }
          ]
        }
      ]
    }
    

通用更新查询语句

使用updateOne结合聚合管道,可同时适配两种场景:

// 定义操作参数
const params = {
  originLessonId: 'lesson1',
  targetLessonId: 'lesson2',
  contentId: 'content1',
  index: 1
};

db.collection.updateOne(
  {}, // 可根据实际需求添加文档匹配条件
  [
    {
      $set: {
        lessons: {
          $map: {
            input: "$lessons",
            as: "lesson",
            in: {
              $cond: [
                { $eq: ["$$lesson._id", params.originLessonId] },
                // 处理源课时:移除指定content
                {
                  _id: "$$lesson._id",
                  title: "$$lesson.title",
                  contents: {
                    $filter: {
                      input: "$$lesson.contents",
                      as: "content",
                      cond: { $ne: ["$$content._id", params.contentId] }
                    }
                  }
                },
                {
                  $cond: [
                    { $eq: ["$$lesson._id", params.targetLessonId] },
                    // 处理目标课时:插入content到指定位置
                    {
                      _id: "$$lesson._id",
                      title: "$$lesson.title",
                      contents: {
                        $let: {
                          vars: {
                            targetContent: {
                              $first: {
                                $filter: {
                                  input: "$lessons.contents",
                                  as: "c",
                                  cond: {
                                    $and: [
                                      { $eq: ["$$c._id", params.contentId] },
                                      { $eq: [{ $arrayElemAt: ["$lessons", { $indexOfArray: ["$lessons._id", params.originLessonId] }] }._id, params.originLessonId] }
                                    ]
                                  }
                                }
                              }
                            }
                          },
                          in: {
                            $concatArrays: [
                              { $slice: ["$$lesson.contents", params.index] },
                              ["$$targetContent"],
                              { $slice: ["$$lesson.contents", params.index, { $size: "$$lesson.contents" }] }
                            ]
                          }
                        }
                      }
                    },
                    // 其他课时保持原样
                    "$$lesson"
                  ]
                }
              ]
            }
          }
        }
      }
    }
  ]
);

语句逻辑说明

  1. 遍历课时数组:用$map对每个课时进行判断,区分源课时、目标课时和普通课时
  2. 源课时处理:通过$filter移除指定contentId的内容
  3. 目标课时处理:
    • 先从源课时中筛选出要移动的content对象
    • 再用$concatArrays和$slice将content插入到指定索引位置
  4. 自动适配同课时场景:当originLessonId与targetLessonId相同时,源课时先移除内容,目标课时(同一课时)再插入该内容,实现位置调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 07:25:09