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

MongoDB聚合操作:将NFT元数据traits数组转换为结构化对象

MongoDB聚合管道实现NFT元数据traits字段转换

你可以根据你的MongoDB版本和环境限制选择以下两种实现方案:

方案1:原生操作符实现(兼容性好,无需开启JS执行权限)

适用于MongoDB 4.4及以上版本,全程使用聚合原生操作符,性能更优:

const aggregationPipeline = [
  // 拆分traits数组为单个属性文档
  { $unwind: "$traits" },
  // 生成格式化后的属性键和对应值
  {
    $addFields: {
      traitKey: {
        $replaceAll: {
          input: { $toLower: "$traits.trait_type" },
          find: " ",
          replacement: "_"
        }
      },
      traitValue: "$traits.value"
    }
  },
  // 按文档ID和属性键分组,收集同属性的所有值,同时保留其他原始字段
  {
    $group: {
      _id: {
        docId: "$_id",
        key: "$traitKey"
      },
      id: { $first: "$id" },
      name: { $first: "$name" },
      asset_contract: { $first: "$asset_contract" },
      token_id: { $first: "$token_id" },
      permalink: { $first: "$permalink" },
      background_color: { $first: "$background_color" },
      image_url: { $first: "$image_url" },
      image_preview_url: { $first: "$image_preview_url" },
      animation_url: { $first: "$animation_url" },
      vault_contract: { $first: "$vault_contract" },
      valueList: { $push: "$traitValue" }
    }
  },
  // 处理值格式:单值直接返回,多值保留数组
  {
    $addFields: {
      kvPair: {
        k: "$_id.key",
        v: {
          $cond: {
            if: { $eq: [{ $size: "$valueList" }, 1] },
            then: { $first: "$valueList" },
            else: "$valueList"
          }
        }
      }
    }
  },
  // 按文档ID重新聚合,收集所有属性键值对
  {
    $group: {
      _id: "$_id.docId",
      id: { $first: "$id" },
      name: { $first: "$name" },
      asset_contract: { $first: "$asset_contract" },
      token_id: { $first: "$token_id" },
      permalink: { $first: "$permalink" },
      background_color: { $first: "$background_color" },
      image_url: { $first: "$image_url" },
      image_preview_url: { $first: "$image_preview_url" },
      animation_url: { $first: "$animation_url" },
      vault_contract: { $first: "$vault_contract" },
      traits: { $push: "$kvPair" }
    }
  },
  // 将键值对数组转换为目标对象结构
  {
    $addFields: {
      traits: { $arrayToObject: "$traits" }
    }
  }
]

方案2:JS自定义函数实现(代码简洁,仅单个阶段)

适用于允许运行JS脚本的MongoDB环境,代码更短易维护:

const aggregationPipeline = [
  {
    $addFields: {
      traits: {
        $function: {
          body: function(traits) {
            const result = {}
            traits.forEach(trait => {
              // 格式化键名:转小写+空格替换为下划线
              const key = trait.trait_type.toLowerCase().replaceAll(' ', '_')
              // 处理值:同键存在则转为数组存储
              if (Object.prototype.hasOwnProperty.call(result, key)) {
                result[key] = Array.isArray(result[key]) 
                  ? [...result[key], trait.value] 
                  : [result[key], trait.value]
              } else {
                result[key] = trait.value
              }
            })
            return result
          },
          args: ["$traits"],
          lang: "js"
        }
      }
    }
  }
]

两种方案都完全符合你要求的转换规则,输出结果和你给出的期望结构一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 17:57:04