如何将字段(即具有K-V对的对象数组)转换为仅具有值的数组数组?

时间:2018-10-15 17:52:37

标签: arrays mongodb aggregation-framework pymongo geojson

我在MongoDB中有一个集合,其中有一个名为“ geometry” 的字段,其纬度和经度是这样的:

{ 
    "abc":"xyz",
    "geometry" : [
        {
            "lat" : 45.0, 
            "lng" : 25.0
        }, 
        {
            "lat" : 46.0, 
            "lng" : 26.0
        }
    ]
}

我想将字段 geometry 转换为类似这样的格式,以符合GeoJSON格式:

{
            "abc":"xyz",
            "geometry": {
            "type": "LineString",
                "coordinates": [
                    [
                        25.0,
                        45.0
                    ],
                    [
                        26.0,
                        46.0
                    ]
                ]                
            }
}

本质上,该操作涉及获取具有两个K / V对的对象数组,并仅选择值并将它们存储为数组数组(顺序相反-因此,值“ lng”排在最前面)。

我的尝试失败: 我尝试使用聚合并尝试投影以下内容:

"geometry": {"type":"LineString", "coordinates":["$points.lng","$points.lat"] }

给我的结果类似于:

"geometry": {
        "type": "LineString",
            "coordinates": [
                [
                    25.0,
                    26.0
                ],
                [
                    45.0,
                    46.0
                ]
            ]                
        }

我尝试使用此方法并逐条记录修改数据记录,但是结果不一致。而且,我试图避免遍历每条记录并一一更改结构。有办法有效地做到这一点吗?

1 个答案:

答案 0 :(得分:1)

您认为以下代码应从理论上讲起作用:

db.collection.aggregate({
    $project: {
        "abc": 1, // include the "abc" field in the output
        "geometry": { // add a new geometry sub-document
            "type": "LineString", // with the hardcoded "type" field
            "coordinates": {
                $map: {
                    "input": "$geometry", // transform each item in the "geometry" array
                    "as": "this",
                    "in": [ "$$this.lng", "$$this.lat" ] // into an array of values only, ith "lng" first, "lat" second
                }
            }
        }
    }
}, {
    $out: "result" // creates a new collection called "result" with the transformed documents in it
})

但是,根据SERVER-37635,MongoDB在此阶段的工作方式是上述查询产生了令人惊讶的输出,其中coordinates字段多次包含所需结果。因此,以下查询可用于生成所需的输出:

db.collection.aggregate({
    $addFields: {
        "abc": 1,
        "geometry2": {
            "type": "LineString",
            "coordinates": {
                $map: {
                    "input": "$geometry",
                    "as": "this",
                    "in": [ "$$this.lng", "$$this.lat" ]
                }
            }
        }
    }
}, {
    $project: {
        "abc": 1,
        "geometry": "$geometry2"
    }
}, {
    $out: "result"
})

在上述JIRA故障单的注释部分中,Charlie Swanson提到了另一种解决方法,该解决方法使用$let“欺骗” MongoDB以所需的方式解释查询。我在此处重新发布(请注意,它缺少$out部分):

db.collection.aggregate([
  {
    $project: {
      "abc": 1,
      "geometry": {
        $let: {
          vars: {
            ret: {
              "type": "LineString",
              "coordinates": {
                $map: {
                  "input": "$geometry",
                  "as": "this",
                  "in": [
                    "$$this.lng",
                    "$$this.lat"
                  ]
                }
              }
            }
          },
          in: "$$ret"
        }
      }
    }
  }
])