我目前正在修改架构,我需要使用聚合框架和bulkWrite
进行相对简单的转换。
我希望能够接受这个数组:
{
...,
"images" : [
"http://example.com/...",
"http://example.com/...",
"http://example.com/..."
]
}
并聚合到一个类似的数组,其中原始值被封装:
{
...,
"images" : [
{url: "http://example.com/..."},
{url: "http://example.com/..."},
{url: "http://example.com/..."}
]
}
此 慢 查询有效,但展开整个集合的成本非常昂贵。
[
{
$match: {}
},
{
$unwind: {
path : "$images",
}
},
{
$group: {
_id: "$_id",
images_2: {$addToSet: {url: "$images"}}
}
},
]
如何通过project
或其他更便宜的汇总来实现这一目标?
答案 0 :(得分:3)
$map表达式可以完成这项工作,试试这个:
db.col.aggregate([
{
$project: {
images: {
$map: {
input: '$images',
as: 'url',
in: {
url: '$$url'
}
}
}
}
}
]);
答案 1 :(得分:1)
您无需使用bulkWrite()
方法。
您可以使用$map
聚合数组运算符将表达式应用于数组中的每个元素元素。
这里,表达式只是创建一个新对象,其中值是数组中的项。
let mapExpr = {
"$map": {
"input": "$images",
"as": "imageUrl",
"in": { "url": "$$imageUrl }
}
};
最后,您可以使用$out
聚合管道运算符覆盖您的集合或将结果写入不同的集合。
当然$map
不是聚合管道运算符,这意味着必须在管道阶段使用$map
表达式。
执行此操作的方式取决于您的MongoDB版本。
最好的方法是在MongoDB 3.4中使用$addFields
来更改文档中“images”字段的值。
db.collection.aggregate([
{ "$addFields": { "images": mapExpr }},
{ "$out": "collection }
])
从MongoDB 3.2向后,您需要使用$project
管道阶段,但还需要在文档中手动包含所有其他字段
db.collection.aggregate([
{ "$project": { "images": mapExpr } },
{ "$out": "collection }
])