在MongoDB中按多边形分组

时间:2014-05-12 04:03:21

标签: ruby mongodb polygon geospatial

我有一个包含多边形的json,这些多边形代表一个国家/地区所有城市的分隔符(总共78个)。例如:

{
    "City1":[
        [-67.103276,18.513426],
        [-67.10339411502086,18.514532657212502],
        [-67.093752,18.515757],
        [-67.05297606966441,18.512073045833525]
    ],
    "City2":[
        [-67.16901339052771,18.472154288860388],
        [-67.169016,18.478488],
        [-67.138249,18.507776],
        [-67.12906260088943,18.510642646697203],
        [-67.125655,18.511706]
    ],
    "City3":[
        [-66.034932,18.333452],
        [-66.03494,18.332214],
        [-66.035911,18.328084],
        [-66.035731,18.31961],
        [-66.036859,18.318627]
    ],
    ...
}

我正在使用MongoDB的ruby驱动程序。该数据库包含一组点(索引为2dsphere)。我需要计算一个城市内的总点数。结果应该说,例如," City1包含56个点,City2包含40个点,City3包含100个点"。

这是我用来查找单个多边形内的点,并设置日期范围from_date到end_date的代码(因为这些点具有日期属性)

polygon = [[-67.103276,18.513426],[-67.10339411502086,18.514532657212502],[-67.093752,18.515757],[-67.05297606966441,18.512073045833525]]
from_date = DateTime.strptime(params[:from_date], '%Y-%m-%d')
from_date = Time.utc(from_date.year, from_date.month, from_date.day)
to_date = DateTime.strptime(params[:to_date], '%Y-%m-%d')
to_date = Time.utc(to_date.year, to_date.month, to_date.day)

@coll = db.collection("points")
recordset = @coll.find(
    { 
        "$and" => [
            { "geometry.coordinates" => {
                "$within" => {"$polygon" => polygon}
            }}, 
            { "properties.time" => {
                :$gte => from_date,
                :$lte => to_date
            }}
        ]
    },
    :fields => { :_id => false }
)

有什么方法可以用一个查询对所有城市的结果进行分组,或者我必须查询数据库78次以获得每个城市的计数?

1 个答案:

答案 0 :(得分:0)

如果您想要group,则需要使用aggregation framework。您将需要一个包含两个步骤的聚合管道和一个可选的第三步:

  1. 使用$match运算符的上述查询(顺便说一下:$并且是不必要的。您可以将"geometry.coordinates""properties.time"放在同一个关联数组中)
  2. _id => "$cityname"运营商"number_of_points" => { "$sum" => 1 }(我猜测城市名称是存储城市名称的字段)和{{1}}。新字段number_of_points将包含每个城市的点数。
  3. (可选)城市名称现在位于_id字段中。如果您希望该字段具有不同的名称,则可以使用其他$group步骤重命名该字段。