mongoDB聚合 - 用动态键在对象中的值执行总和

发布于 2025-02-02 03:38:32 字数 774 浏览 2 评论 0原文

假设我有以下集合,_id特质

[
    {
      _id: 1,
      traits: {
        Rarity: {
          infoin: 15,
        },
        Type: {
          iron: 3,
          sliver: 5,
          wood: 7,
        },
      },
    },
    {
      _id: 2,
      traits: {
        Cloth: {
          barron1: 11,
          barron2: 12,
        },
        Hair: {
          black: 6,
          yellow: 9,
          red: 8
        }
      },
    },
    ...
]

如您所见,特征的键是动态的,也是子对象的键。

这是我想得到的结果:

[
    {
      _id: 1,
      traits: 15,
    },
    {
      _id: 2,
      traits: 23
    }
]

提示:

infocoin =铁 + sliver +木材

barron1 + barron2 =黑色 +黄色 +红色

Let's say I have the following collection with _id and traits.

[
    {
      _id: 1,
      traits: {
        Rarity: {
          infoin: 15,
        },
        Type: {
          iron: 3,
          sliver: 5,
          wood: 7,
        },
      },
    },
    {
      _id: 2,
      traits: {
        Cloth: {
          barron1: 11,
          barron2: 12,
        },
        Hair: {
          black: 6,
          yellow: 9,
          red: 8
        }
      },
    },
    ...
]

As you can see keys of traits are dynamic and the keys of sub-objects as well.

Here is the result I wanna get:

[
    {
      _id: 1,
      traits: 15,
    },
    {
      _id: 2,
      traits: 23
    }
]

Tip:

infocoin = iron + sliver + wood

barron1 + barron2 = black + yellow + red

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

站稳脚跟 2025-02-09 03:38:32
  1. $ set - set traitobjs数组字段通过通过$ objectToArray将对象转换为数组

  2. $ set - set firstTraitValues字段通过从traitobjs数组中获取第一个文档的值,然后通过$ objecttoaray 。

  3. $ project - 装饰输出文档。 SET 特征字段通过转换firstTraitValues带有$ yrumend类型的数组$ sum所有v值。

db.collection.aggregate([
  {
    $set: {
      traitObjs: {
        $objectToArray: "$traits"
      }
    }
  },
  {
    $set: {
      firstTraitValues: {
        $objectToArray: {
          $first: "$traitObjs.v"
        }
      }
    }
  },
  {
    $project: {
      traits: {
        $reduce: {
          input: "$firstTraitValues",
          initialValue: 0,
          in: {
            $sum: [
              "$value",
              "$this.v"
            ]
          }
        }
      }
    }
  }
])

示例mongo playground


因为第一个密钥文档中的所有值和第二个关键文档和特征是相同的,

infocoin =铁 + sliver +木材

barron1 + barron2 =黑色 +黄色 +红色

因此上述方法仅在特征的第一个关键文档中总结了所有值。

  1. $set - Set traitObjs array field by converting the object to array via $objectToArray.

  2. $set - Set firstTraitValues field by getting the value of first document from traitObjs array, then converting from object to array via $objectToArray.

  3. $project - Decorate the output document. Set traits field by converting firstTraitValues array to number type with $reduce and $sum all the v values.

db.collection.aggregate([
  {
    $set: {
      traitObjs: {
        $objectToArray: "$traits"
      }
    }
  },
  {
    $set: {
      firstTraitValues: {
        $objectToArray: {
          $first: "$traitObjs.v"
        }
      }
    }
  },
  {
    $project: {
      traits: {
        $reduce: {
          input: "$firstTraitValues",
          initialValue: 0,
          in: {
            $sum: [
              "$value",
              "$this.v"
            ]
          }
        }
      }
    }
  }
])

Sample Mongo Playground


Since all the values in the first key document and the second key document of traits are the same,

infocoin = iron + sliver + wood

barron1 + barron2 = black + yellow + red

Hence the above approach just sums up all the values in the first key document of traits.

泪冰清 2025-02-09 03:38:32

这个答案确实与 @yong-shun的答案,但它构成了一个“ $ project” $ project'< /代码>。我不知道这是否会更有效。

db.collection.aggregate([
  {
    "$project": {
      "traits": {
        "$reduce": {
          "input": {
            "$objectToArray": {
              "$getField": {
                "field": "v",
                "input": { "$first": { "$objectToArray": "$traits" } }
              }
            }
          },
          "initialValue": 0,
          "in": { "$sum": [ "$value", "$this.v" ] }
        }
      }
    }
  }
])

尝试一下 mongoplayground.net.net

This answer is really the same as @yong-shun's answer but it composes everthing into one "$project". I don't know if it would be more efficient or not.

db.collection.aggregate([
  {
    "$project": {
      "traits": {
        "$reduce": {
          "input": {
            "$objectToArray": {
              "$getField": {
                "field": "v",
                "input": { "$first": { "$objectToArray": "$traits" } }
              }
            }
          },
          "initialValue": 0,
          "in": { "$sum": [ "$value", "$this.v" ] }
        }
      }
    }
  }
])

Try it on mongoplayground.net.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文