由$ geonear汇总

时间:2016-11-25 13:37:53

标签: node.js mongodb aggregation-framework geospatial geojson

我有一个看起来像这样的集合:

[
  {
    "roadname": "foo",
    "data": [
      {
        "val": 50,
        "loc": {
          "type": "Point",
          "coordinates": [3.197033554, 50.64611712]
          }
        }
      },
      {
        "val": NULL,
        "loc": {
          "type": "Point",
          "coordinates": [3.197740735, 50.6460058]
          }
        }
      }
    ]
  },
  {
    "roadname": "foo",
    "data": [
      {
        "val": 50,
        "loc": {
          "type": "Point",
          "coordinates": [3.32456512, 50.2744516]
          }
        }
      }
    ]
  },
  {
    "roadname": "bar",
    "data": [
      {
        "val": 145,
        "loc": {
          "type": "Point",
          "coordinates": [3.198408689, 50.64586985]
          }
        }
      }
    ]
  }
]

我在地图上显示每个data.loc,这导致我: dispatched points。 (点颜色代表val字段)

EDIT3:为了阐明我的数据库结构,这里是确切数据库的表示。每个灰线表示来自提供的数据集的根元素: lines points

我想“群组点靠近(使用data.loc),并且拥有相同的父name ”,并汇总其val(用平均值来说明这一点很简单),为了显示如下内容: aggregated points

EDIT3:重要的是要了解我正在尝试聚合的内容不共享任何共同财产或祖先。他们的 ONLY 普通的denomitator是他们的空间接近度

我知道neargeoneargroup聚合,但我无法找到解决方案来执行此操作。

我想使用纯粹的mongodb解决方案。如果不可能,我也可以使用turf.js或其他库,但我只是在努力寻找一种可行且可扩展的方法来实现这一目标。

编辑:集合中的主要根元素代表道路,因此道路上的所有点都具有相同的父roadname

EDIT2 :可以找到数据 here

1 个答案:

答案 0 :(得分:1)

我认为这对你有用。我将您的数据集aggregatingpointsdata.json导入名为roads的mongo集合。

这是一个集群在mongo中的样子。因此,每个文档都代表一个集群,或者您提供的数据集中数组中的一个元素。要记住的一件事是,只有当应该组合在一起的点群集有一些标识符时,这才会起作用。在我的示例中,它是_id

> db.roads.findOne()
{
        "_id" : ObjectId("583ee50bd7c4d711d45c7757"),
        "roadname" : "RD700",
        "data" : [
                {
                        "val" : null,
                        "loc" : {
                                "type" : "Point",
                                "coordinates" : [
                                        3.197033554,
                                        50.64611712
                                ]
                        }
                },
                {
                        "val" : null,
                        "loc" : {
                                "type" : "Point",
                                "coordinates" : [
                                        3.197740735,
                                        50.6460058
                                ]
                        }
                },
                {
                        "val" : 145,
                        "loc" : {
                                "type" : "Point",
                                "coordinates" : [
                                        3.198408689,
                                        50.64586985
                                ]
                        }
                },
          ]
}

这是您可以运行的mongo聚合,它将返回每个群集的平均值。我甚至让它返回相同的GeoJSON格式。

db.roads.aggregate([
    //unravel the cluster here
    { $unwind: "$data" },
    //project the coordinates to more readable names while preserving roadname and GeoJSON type.
    { $project: {roadname: 1, type: "$data.loc.type", val : "$data.val", lng: { $arrayElemAt: ["$data.loc.coordinates",0]}, lat: { $arrayElemAt: ["$data.loc.coordinates",-1]}}},
    //group on cluster id while preserving type and roadname. Take avergae of value, lat and long.
    { $group: { _id : "$_id", roadname: {$first:"$roadname"}, type: {$first: "$type"}, avgLng: { $avg: "$lng" },avgLat: { $avg: "$lat" }, avgVal: { $avg : "$val" }}},
    //re-project to fit the similar format of original collection
    { $project: { _id: 1, roadname: 1,  data : { val: "$avgVal", loc: {type : "$type", coordinates: ["$avgLng", "$avgLat"]}} }}
])

您还可以在聚合管道的末尾添加额外的$out,以将所有这些平均质心移动到另一个更易于管理的集合。

以上是上面显示的聚合管道调用后的结果。

[
  {
    "_id": ObjectId("583ee50bd7c4d711d45c775c"),
    "roadname": "RD700",
    "data": {
      "val": 144.03703703703704,
      "loc": {
        "type": "Point",
        "coordinates": [
          3.2232721289257142,
          50.67602178708569
        ]
      }
    }
  },
  {
    "_id": ObjectId("583ee50bd7c4d711d45c775b"),
    "roadname": "RD700",
    "data": {
      "val": 170.0344827586207,
      "loc": {
        "type": "Point",
        "coordinates": [
          3.22367598656322,
          50.67626952408046
        ]
      }
    }
  },
  ...
]