mongodb - 如何使用聚合框架创建新的数组字段

标签 mongodb mongodb-query aggregation-framework

我开始使用 mongoDb,但我遇到了一个简单的用例。

假设我有一个集合“aCollection”,其中包含如下条目:

{ 
    _id: ObjectId(123),
    lat: 48,56623,
    long: 2,56332
}

我想创建一个包含如下条目的新集合:

{ 
    _id: ObjectId(123),
    lat: 48,56623,
    long: 2,56332,
    geometry : { 
        type: "Point",
        coordinates: [48,56623, 2,56332]
    }
}

我考虑了聚合框架:

db.aCollection.aggregate([{$project: { 
    _id: 1,
    lat: 1,
    long: 1,
    geometry: { 
        type: {$concat: ["Point"]},
        coordinates: ["$lat", "$long"]
    }
}}])

但它不起作用,我得到了这个异常:

“异常:对象表达式中不允许使用字段类型数组(在‘坐标’处)”

以下聚合有效,但未产生预期结果:

db.aCollection.aggregate([{$project: { 
    _id: 1,
    lat: 1,
    long: 1,
    geometry: { 
        type: {$concat: ["Point"]},
        coordinates: "$lat"
    }
}}])

您将如何继续创建此集合 1)使用聚合框架 2)没有聚合框架

谢谢

最佳答案

在现代 MongoDB 版本中,最有效的方法是使用现有文档属性简单地注释数组。 MongoDB 3.2 中引入了数组的直接表示法:

db.collection.aggregate([
  { "$project": {
    "lat": 1,
    "long": 1,
    "geometry": {
      "type": { "$literal": "Point" },
      "coordinates": [ "$lat", "$long" ]
    }
  }},
  { "$out": "newcollection" }
])

或者甚至使用 $addFields只需将新属性“附加”到文档中即可:

db.collection.aggregate([
  { "$addFields": {
    "geometry": {
      "type": { "$literal": "Point" },
      "coordinates": [ "$lat", "$long" ]
    }
  }},
  { "$out": "newcollection" }
])
<小时/>

如果您使用的是 MongoDB 2.6 及更高版本,您可以使用聚合框架来执行此操作,并避免在客户端程序中循环结果以创建新集合。

这里可以帮助您的主要功能是 $out用于将输出发送到新集合的运算符。但也要聪明一点才能创建您需要的数组。

db.collection.aggregate([
    { "$project": {
        "lat": 1,
        "long": 1,
        "type": { "$literal": ["lat","long"] }
    }},
    { "$unwind": "$type" },
    { "$group": {
        "_id": "$_id",
        "lat": { "$first": "$lat" },
        "long": { "$first": "$long" },
        "coordinates": {
            "$push": {
                "$cond": [
                    { "$eq": [ "$type", "lat" ] },
                    "$lat",
                    "$long"
                ]
            }
        }
    }},
    { "$project": {
        "lat": 1,
        "long": 1,
        "geometry": { 
            "type": { "$literal": "Point" },
            "coordinates": "$coordinates"
        }
    }},
    { "$out": "newcollection" }
])

所以这利用了 $literal运算符以在管道的头部指定一个新数组。该运算符将完全按照提供内容的方式将内容放入文档属性中。因此不允许变量替换,因此是“字面的”。

为了创建“coordintes”数组,我们只需展开第一个数组,该数组实际上创建了每个文档中的两个“type”值不同的文档。然后将其用于 $group有条件地阶段到$push将“$lat”或“$long”值添加到该数组中。

最后使用$project再次确定文档结构,然后 $out将所有输出发送到新集合。

<小时/>

请注意,只有当您打算创建新集合并避免“通过线路”发送流量时,这才有意义。这不能纯粹在聚合框架中用于重新调整文档,以便在同一聚合管道中执行“地理空间”查询,因为“地理空间”查询仅在实际对集合建立索引时才起作用.

因此,这可能会帮助您根据需要创建一个新集合,但至少它可以作为如何使用聚合框架从不同值创建数组的示例(实际上是两个示例)。

关于mongodb - 如何使用聚合框架创建新的数组字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23961368/

相关文章:

mongodb - Mongoose 似乎无法汇总总和并返回所有项目

mongodb - 最佳数据记录数据库

arrays - 如何在 mongodb 中更新多个数组元素

node.js - 在mongodb聚合中仅提取$project中键值对中的值

mongodb - 如何在mongodb中选择嵌套数组的字段和计数

java - 对 Spring Data Mongo 存储库提供限制

node.js - Stripe : No such token Error

java - 删除[ "": from mongoDb result using Java

mongodb - 如何在多个字段中搜索文本或表达式

java - mongodb java 驱动程序。如何通过引用返回对象