Mongodb 将数组封装/转换为对象数组

Mongodb 将数组封装/转换为对象数组,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我目前正在修改模式,需要使用聚合框架和 我希望能够获取此阵列: { ..., "images" : [ "http://example.com/...", "http://example.com/...", "http://example.com/..." ] } 并聚合到一个类似的数组中,在该数组中封装原始值: { ..., "images" : [ {url: "htt

我目前正在修改模式,需要使用聚合框架和

我希望能够获取此阵列:

{ 
     ...,
     "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
或其他更便宜的聚合实现这一点?

expression应该完成这项工作,请尝试以下方法:

db.col.aggregate([
  {
    $project: {
      images: {
        $map: {
          input: '$images',
          as: 'url',
          in: {
            url: '$$url'
          }
        }
      }
    }
  }
]);

您不需要为此使用
bulkWrite()
方法

可以使用聚合数组运算符将表达式应用于数组中的每个元素

这里,表达式只是创建一个新对象,其中值是数组中的项

let mapExpr = {
    "$map": {
        "input": "$images",
        "as": "imageUrl",
        "in": { "url": "$$imageUrl }
    }
};
最后,您可以使用
$out
聚合管道操作符覆盖集合或将结果写入其他集合

[
    {
        $match: {}
    },
    {
        $unwind: {
            path : "$images",
        }
    },
    {
        $group: {
            _id: "$_id",
            images_2: {$addToSet: {url: "$images"}}
        }
    },
]
当然,
$map
不是聚合管道操作符,因此这意味着必须在管道阶段使用
$map
表达式

这取决于您的MongoDB版本

最好的方法是在MongoDB 3.4中使用更改文档中“images”字段的值

db.collection.aggregate([
    { "$addFields": { "images": mapExpr }},
    { "$out": "collection }
])
从MongoDB 3.2向后看,您需要使用pipeline阶段,但也需要在文档中手动包含所有其他字段

db.collection.aggregate([
    { "$project": { "images": mapExpr } },
    { "$out": "collection }
])