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

TypeScript合并MongoDB同类型attributes并更新的技术问询

合并MongoDB文档中attributes数组的指定类型对象并更新

原始数据示例

{
  "_id": ObjectId("60d21b4667d0d8992e610c85"),
  "attributes": [
    { "type": "allergens", "value": "花生" },
    { "type": "allergens", "value": "牛奶" },
    { "type": "category", "value": "零食" },
    { "type": "allergens", "value": "坚果" }
  ]
}

目标数据示例

{
  "_id": ObjectId("60d21b4667d0d8992e610c85"),
  "attributes": [
    { "type": "category", "value": "零食" },
    { "type": "allergens", "value": ["花生", "牛奶", "坚果"] }
  ]
}

方案一:MongoDB聚合管道直接更新(推荐)

直接在数据库层完成合并逻辑,无需将数据拉取到应用层,性能更优,适合批量处理。

TypeScript代码实现

import { MongoClient } from 'mongodb';

async function mergeAllergens() {
  const client = await MongoClient.connect('mongodb://localhost:27017');
  const db = client.db('your-db-name');
  const collection = db.collection('your-collection-name');

  await collection.updateMany(
    // 匹配包含至少一个allergens类型属性的文档
    { "attributes.type": "allergens" },
    [
      {
        $set: {
          attributes: {
            $concatArrays: [
              // 保留所有非allergens类型的属性
              {
                $filter: {
                  input: "$attributes",
                  cond: { $ne: ["$$this.type", "allergens"] }
                }
              },
              // 合并所有allergens属性为单个对象,value转为数组
              [
                {
                  type: "allergens",
                  value: {
                    $map: {
                      input: {
                        $filter: {
                          input: "$attributes",
                          cond: { $eq: ["$$this.type", "allergens"] }
                        }
                      },
                      in: "$$this.value"
                    }
                  }
                }
              ]
            ]
          }
        }
      }
    ]
  );

  await client.close();
}

mergeAllergens().catch(console.error);

逻辑说明

  1. 使用$filter筛选出所有非allergens类型的属性,保留原结构
  2. 再次筛选出所有allergens类型的属性,通过$map提取value字段组成数组,包装成单个allergens对象
  3. 用$concatArrays将两部分数据合并为新的attributes数组,通过$set更新到文档中
  4. 若需要对value去重,可将$map替换为$setUnion: [{ $map: ... }]

方案二:TypeScript应用层处理后更新

适合需要在合并前添加额外业务逻辑(如数据校验、格式转换)的场景。

TypeScript代码实现

import { MongoClient } from 'mongodb';

async function processAndMergeAllergens() {
  const client = await MongoClient.connect('mongodb://localhost:27017');
  const db = client.db('your-db-name');
  const collection = db.collection('your-collection-name');

  // 查询所有包含allergens属性的文档
  const targetDocs = await collection.find({ "attributes.type": "allergens" }).toArray();

  for (const doc of targetDocs) {
    // 分离非allergens属性和allergens属性值
    const nonAllergenAttrs = doc.attributes.filter(item => item.type !== 'allergens');
    const allergenValues = doc.attributes
      .filter(item => item.type === 'allergens')
      .map(item => item.value)
      .filter((val, idx, self) => self.indexOf(val) === idx); // 可选:去重

    // 构建新的attributes数组
    const updatedAttributes = [...nonAllergenAttrs, { type: 'allergens', value: allergenValues }];

    // 更新单个文档
    await collection.updateOne(
      { _id: doc._id },
      { $set: { attributes: updatedAttributes } }
    );
  }

  await client.close();
}

processAndMergeAllergens().catch(console.error);

注意事项

  • 若处理大量文档,方案二性能弱于方案一,需谨慎使用
  • 执行更新前建议先通过find语句验证处理逻辑,避免误操作
  • 可根据业务需求调整allergenValues的处理逻辑(如排序、格式转换)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:25:21