我有一个包含部门 ID 数组的子文档的数据结构,这些部门 ID 是包含 ID 和部门名称的对象。人们可能在很多部门,并且每个部门都有一个单独的 ID,因此他们的记录可能如下所示:
{
"_id" : "xxxxx",
"dept_ids" : [
{
"dept_id" : "dd7867535",
"dept_name" : "d1"
},
{
"dept_id" : "dl97087079",
"dept_name" : "d2"
}
]
}
我正在将一个具有已知部门子集的聚合查询放在一起,我想使用“dept_name”的值来汇总这些值,以便生成的文档如下所示:
{
"_id" : "xxxxx",
"d1" : "dd7867535",
"d2" : "dl97087079"
}
我在聚合框架内找不到执行此操作的方法。欢迎大家提出意见。
谢谢,亚历克斯
如果你真的有一个 MongoDB 支持$replaceRoot
,$arrayToObject
那么你可以使用这个:
db.collection.aggregate([
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{ "_id": "$_id" },
{ "$arrayToObject": {
"$map": {
"input": "$dept_ids",
"in": { "k": "$$this.dept_name", "v": "$$this.dept_id" }
}
}}
]
}
}}
])
但是您甚至不需要它,只需转换返回的文档即可:
db.collection.find().map(d =>
Object.assign(
{ _id: d._id },
d.dept_ids.reduce((acc,dep) => Object.assign(acc,{ [dep.dept_name]: dep.dept_id }), {})
)
);
在现代 ECMASCRIPT 环境中,不是 Mongo shell,而是像 NodeJS 这样的东西,你可以稍微清理一下语法。即使用 NodeJS 驱动程序:
const mapper = ({ _id, dept_ids }) => ({
_id, ...dept_ids.reduce((acc, { dept_name: k, dept_id: v }) => ({ ...acc, [k]: v }),{})
});
let results = await db.collection('departments').find().map(mapper).toArray();
两者都产生相同的结果:
{ "_id" : "xxxxx", "d1" : "dd7867535", "d2" : "dl97087079" }
所以你真的不需要通过聚合管道来处理事情,这可以很简单地从客户端接收到的数据完成。您没有“减少”任何数据,这实际上是聚合框架的重点。所以像这样的转换真的“应该”在后处理游标结果中完成。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句