2016-04-15 49 views
6

我試圖建立一個基於地圖的可視化,包括亞羣的「熱圖」的基礎上,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和一些插件來呈現這些數據的各種可視化。傳單在客戶端的聚類數據方面非常出色 - 所以如果我將它傳遞給具有密度值的上千個位置,則只需通過處理所有單個值就可以渲染相關區域的熱圖。

問題是,比如說我縮小地圖來展示整個世界。如果不是不可能的話,將所有這些數據發送給客戶端並使其足夠快地處理該信息以實現流暢的可視化將是非常低效的。

所以我需要做的是自動集羣數據服務器端,我希望可以在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 

這將決定簇需要的精細程度是基於個別點有多少是特定地理區域內,給定最大數量的數據點返回,或沿着這些線;它會返回的數據是這樣的:

[ 
    { "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查詢中完成的事情嗎?有沒有一種「經過嘗試和測試」的方式來做到這一點?

+1

這將是困難的只是原始數據沒有一些預先分配的「聚類」概念,或者通過額外的「屬性」或者簡單地預先聚合到粒度爲「縮放級別」的其他收集數據。正如我對單個查詢處理所看到的基本問題是,雖然您可以使用'$ geoNear'來確定與中心點(例如區域選擇的中心)的接近程度,但這個「會」會讓您從該點到「羣集「在,但是它沒有考慮到與他們自己接近的點。所以你基本上需要「迭代」點數據來找到最近的點。 –

+1

上面的TLDR是*,「沒有預先計算的集羣分配,這不是很高效」*。 –

回答

4

即使您在運行時執行此查詢,它將效率低下並且不會很快被視爲良好的用戶界面。 我建議你預先生成特定大小的集羣,並將它們與原始文檔一起保存在當前集合中。 方法如下:

  • 每個文件將存儲的附加字段(可以稱之爲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半徑範圍內的幾個城市的集羣,其中3個將成爲geolevel集羣:2個集羣。

    • 您還可以存儲像memberids這樣的字段,以存儲每個羣集中 中兒童的ID。這可能有必要避免一個實體進入兩個相鄰的簇,它可以被分配給任何一個相鄰的簇,並且您的可視化仍然可以正常工作。 一個geolevel:2叢集文件看起來像:

      { 
          "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 
      } 
      
    • 現在你的可視化應用程序需要做縮放級別的映射geolevel,並根據您將選擇您的文件。對於城市級的可視化,可以爲geolevel查詢:1個文件,併爲你縮小到省,國家等可以增加geolevel 2,3 ...
+0

我真的很喜歡這種方式構建層次結構的方法。看起來像構建生成這些文檔的機制的一個相當簡單的任務。非常感激。 – DanM