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

Mongoose实现嵌套数组产品更新/新增及缺失路径自动创建

基于Mongoose实现嵌套数组产品的更新/插入(自动补全层级)

针对你需要在date/hours[hour]/categories[category]/products路径下更新或添加产品,同时自动创建缺失层级的需求,以下是两种可落地的实现方案:


方案1:分步骤操作(逻辑清晰,易维护)

先尝试更新已存在的产品,若未匹配到目标路径,则手动创建缺失层级并添加/更新产品,避免单次操作的复杂度。

第一步:尝试更新已存在的产品

通过数组定位操作符$结合arrayFilters精准匹配目标层级,直接更新产品:

const updateResult = await YourModel.findOneAndUpdate(
  // 匹配基础路径:date、目标hour、目标category
  {
    date: "05/05/24",
    "hours.hour": "09",
    "hours.categories.category": "computers"
  },
  // 定位目标产品并更新字段
  {
    $set: {
      "hours.$[hourElem].categories.$[catElem].products.$[prodElem].last_published": new Date()
    }
  },
  {
    arrayFilters: [
      { "hourElem.hour": "09" },
      { "catElem.category": "computers" },
      { "prodElem.product_source_id": "112233" }
    ],
    new: true, // 返回更新后的文档
    runValidators: true // 确保符合Schema验证规则
  }
);

第二步:补全缺失层级并添加/更新产品

如果上述操作返回null,说明路径存在缺失,手动创建层级:

if (!updateResult) {
  // 1. 确保date对应的文档存在,不存在则创建
  let doc = await YourModel.findOne({ date: "05/05/24" });
  if (!doc) {
    doc = new YourModel({ date: "05/05/24", hours: [] });
  }

  // 2. 查找或创建目标hour节点
  let hourItem = doc.hours.find(h => h.hour === "09");
  if (!hourItem) {
    hourItem = { hour: "09", categories: [] };
    doc.hours.push(hourItem);
  }

  // 3. 查找或创建目标category节点
  let categoryItem = hourItem.categories.find(c => c.category === "computers");
  if (!categoryItem) {
    categoryItem = { category: "computers", products: [] };
    hourItem.categories.push(categoryItem);
  }

  // 4. 查找或更新/添加产品
  let productItem = categoryItem.products.find(p => p.product_source_id === "112233");
  if (productItem) {
    productItem.last_published = new Date();
  } else {
    categoryItem.products.push({
      product_source_id: "112233",
      last_published: new Date()
    });
  }

  // 保存最终文档
  await doc.save();
}

方案2:原子聚合操作(性能更优,单次DB请求)

利用MongoDB聚合管道的$cond、$map、$concatArrays等操作符,在单次数据库请求中完成层级检查、创建和产品更新/插入,适合对性能要求较高的场景:

await YourModel.findOneAndUpdate(
  { date: "05/05/24" },
  [
    // 步骤1:检查并添加缺失的hour节点
    {
      $set: {
        hours: {
          $cond: [
            { $in: ["09", "$hours.hour"] },
            "$hours",
            { $concatArrays: ["$hours", [{ hour: "09", categories: [] }]] }
          ]
        }
      }
    },
    // 步骤2:检查并添加缺失的category节点
    {
      $set: {
        hours: {
          $map: {
            input: "$hours",
            as: "h",
            in: {
              $cond: [
                { $eq: ["$$h.hour", "09"] },
                {
                  hour: "$$h.hour",
                  categories: {
                    $cond: [
                      { $in: ["computers", "$$h.categories.category"] },
                      "$$h.categories",
                      { $concatArrays: ["$$h.categories", [{ category: "computers", products: [] }]] }
                    ]
                  }
                },
                "$$h"
              ]
            }
          }
        }
      }
    },
    // 步骤3:更新或添加目标产品
    {
      $set: {
        hours: {
          $map: {
            input: "$hours",
            as: "h",
            in: {
              $cond: [
                { $eq: ["$$h.hour", "09"] },
                {
                  hour: "$$h.hour",
                  categories: {
                    $map: {
                      input: "$$h.categories",
                      as: "c",
                      in: {
                        $cond: [
                          { $eq: ["$$c.category", "computers"] },
                          {
                            category: "$$c.category",
                            products: {
                              $cond: [
                                { $in: ["112233", "$$c.products.product_source_id"] },
                                {
                                  $map: {
                                    input: "$$c.products",
                                    as: "p",
                                    in: {
                                      $cond: [
                                        { $eq: ["$$p.product_source_id", "112233"] },
                                        { ..."$$p", last_published: new Date() },
                                        "$$p"
                                      ]
                                    }
                                  }
                                },
                                { $concatArrays: ["$$c.products", [{ product_source_id: "112233", last_published: new Date() }]] }
                              ]
                            }
                          },
                          "$$c"
                        ]
                      }
                    }
                  }
                },
                "$$h"
              ]
            }
          }
        }
      }
    }
  ],
  { upsert: true, new: true, runValidators: true }
);

注意事项

  • 确保product_source_id的类型与Schema定义一致(Schema中为String,需传入字符串类型的ID);
  • 启用runValidators: true可避免更新操作违反Schema的必填项、枚举值等规则;
  • 方案1适合中小规模业务,逻辑直观易调试;方案2适合高并发场景,减少DB交互次数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:35:04