MongoDB:集群文件按地理位置给定区域和最大点?

我正在尝试开发一个基于地图的可视化,其中包含一个基于MongoDB集合的子集的“热图”,其中包含如下文档:

{ "PlaceName" : "Boston", "Location" : { "type" : "Point", "coordinates" : [ 42.358056, -71.063611 ] }, "Subpopulations": { "Age": { "0_4" : 37122, "6_11" : 33167, "12_17" : 35464, "18_24" : 130885, "25_34" : 127058, "34_44" : 79092, "45_54" : 72076, "55_64" : 59766, "65_74" : 33997, "75_84" : 20219, "85_" : 9057 } } } 

数据库中有数十万个单独的位置。 它们重叠 – 即“纽约市”和“曼哈顿”不会有两个单独的条目。

目标是使用Leaflet.js和一些插件来呈现这些数据的各种可视化。 Leaflet在客户端的数据聚类方面相当出色 – 所以如果我通过了一千个具有密度值的位置,只需通过处理所有的单个值就可以渲染相关区域的热图。

问题是,我放大地图来展示整个世界。 如果不是不可能的话,将所有这些数据发送给客户端并且使其足够快地处理该信息以使得可视化可视化将是非常低效的。

所以我需要做的是自动集群数据服务器端,我希望可以在MongoDB查询中完成。 我已经读过, geohashing可能是一个很好的起点,可以确定哪些点属于哪个簇,但是我确定有人以前做过这个确切的事情,并且可能比那个更清晰。 理想情况下,我想发送一个查询到我的node.js脚本看起来像这样:

 http://myserver.com/popdata?top=42.48&left=-80.57&bottom=37.42&right=-62.55&stat=Age&value=6_11 

这将决定聚类需要的粒度如何根据指定地理区域内有多less个点,给定最大数量的返回数据点或沿着这些线的某个点; 它会返回这样的数据:

 [ { "clusterlocation": [ 42.304, -72.622 ], "total_age_6_11": 59042 }, { "clusterlocation": [ 36.255, -64.124 ], "total_age_6_11": 7941 }, { "clusterlocation": [ 40.425, -70.693 ], "total_age_6_11": 90257 }, { "clusterlocation": [ 39.773, -67.992 ], "total_age_6_11": 102752 }, ... ] 

…其中“clusterlocation”类似于集群中文档的所有位置的均值,“total_age_6_11”是“Subpopulations.Age.6_11”的文档值的总和。

这是我可以纯粹在Mongo查询中做的事吗? 有没有一个“尝试和testing”的方式来做到这一点?

即使你在运行时进行这种查询,也会被认为是一个好的用户界面,效率不高并且速度不快。 我build议您预先生成特定大小的集群,并将它们与原始文档一起保存在当前集合中。 这里是如何:

  • 每个文件将存储一个额外的字段(让我们称之为geolevel),这将表示它是多么小或大的实体。 您的基础文档将具有geolevel = 1:

     { "PlaceName" : "Boston", "Location" : { "type" : "Point", "coordinates" : [ 42.358056, -71.063611 ] }, "Subpopulations": { "Age": { "0_4" : 37122, "6_11" : 33167, "12_17" : 35464, "18_24" : 130885, "25_34" : 127058, "34_44" : 79092, "45_54" : 72076, "55_64" : 59766, "65_74" : 33997, "75_84" : 20219, "85_" : 9057 } }, "geolevel":1 // added geolevel } 
    • 您可以在数据库上运行处理,为集群和多个级别预先生成类似的文档。 例如geolevel:2将是半径250kms以内的几个城市的集群,geolevel:3将是geolevel集群:2个集群。

    • 您还可以存储类似于memberids身份的字段,以存储每个群集中子女的ID。 这可能是必要的,以避免一个实体进入两个相邻的群集,它可以被分配到任何一个相邻的群集,你的可视化仍然可以正常工作。 geolevel:2集群doc看起来像:

        { "PlaceName" : "cluster_sdfs34535", // The id can be generated from hash like sha of a list of all children ids. "Location" : { // center of the cluster "type" : "Point", "coordinates" : [ 42.358056, -71.063611 ] }, "Subpopulations": { // total population of the cluster "Age": { "0_4" : 371220, "6_11" : 331670, "12_17" : 354640, "18_24" : 1308850, "25_34" : 1270580, "34_44" : 790920, "45_54" : 720760, "55_64" : 597660, "65_74" : 339970, "75_84" : 202190, "85_" : 90570 } }, "geolevel":2 , "childs":[4,5,6,7] // ids of child documents } 
    • 现在你的可视化应用程序需要做一个zoomlevel到geolevel的映射,并基于这个你将select你的文档。 对于城市级的可视化,你可以查询geolevel:1文件,并且当你缩小状态,国家等,你可以增加geolevel 2,3 …