我的数据结构带有一个包含部门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"
}
我在汇总框架中找不到这样做的方法。任何建议都会受到欢迎。
谢谢, 亚历
答案 0 :(得分:0)
如果你实际上有一个支持$replaceRoot
和$arrayToObject
的MongoDB,那么你可以使用它:
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" }
因此,您真的不需要通过聚合管道处理事务,这可以通过客户端上接收的数据完成。您并没有“减少”任何数据,这实际上是聚合框架的重点。所以这样的转换确实“应该”在后处理光标结果时完成。