2011-04-08 23 views
10

我有一個特定的數據操作要求,我已經計算出如何在SQL Server和PostgreSQL中執行操作。不過,我對速度並不滿意,所以我正在調查MongoDB。MongoDB對分層類型查詢的適用性

描述查詢的最佳方式如下。圖片美國的等級數據:國家,州,縣,市。假設某個特定的供應商可以爲整個加州提供服務。另一個也許只能服務於洛杉磯。潛在的成千上萬的供應商,他們都可以從這個層次結構中的某個點向下服務。我並沒有將這與Geo混淆 - 我用這個來說明需要。

使用遞歸查詢,獲取可以爲特定用戶提供服務的所有供應商的列表非常簡單。如果他在加利福尼亞州洛杉磯的帕薩迪納市,我們會逐步找到適用的ID,然後再查詢以找到供應商。

我知道這可以優化。再次,這只是一個簡單的查詢示例。

我知道MongoDB是一個文檔存儲。這適合我非常好的其他需求。問題是它對我描述的查詢類型有多合適? (我知道它沒有連接 - 這些都是模擬的)。

我知道這是一個「字符串多長時間」的問題。我只是想知道是否有人對MongoDB有這方面的經驗。從0開始測試可能需要相當長的一段時間,如果MongoDB不適合這樣做,我希望節省時間。

本地電影商店 「A」 可以在斯普林菲爾德提供藍光射線。全州分銷連鎖店「B」可以向所有IL提供藍光光盤。一個下載點播商店「C」可以提供給美國的所有用戶。

如果我們想爲伊利諾伊州斯普林菲爾德獲得所有適用的電影供應商,答案將是[A,B,C]。

換句話說,在層次結構上有不同級別的衆多供應商。

+0

傳統上,複合鍵可以很容易地做到這一點。但是,這不是我正在查找的查詢風格。 – IamIC 2011-04-10 07:55:40

回答

7

我意識到這個問題,有人問將近一年前,但此後的MongoDB已正式支持的解決方案對於這個問題,我只是用他們的解決方案。請參閱他們的文檔:http://www.mongodb.org/display/DOCS/Trees+in+MongoDB

與您的問題最接近的部分位於頁面的「部分路徑」部分。

儘管嵌入祖先數據可能感覺有點沉重;這種方法是解決MongoDB中問題的最合適的方法。我迄今所經歷的唯一缺陷是,如果您將所有這些內容存儲在單個文檔中,那麼在處理足夠的數據時,您可以選擇16MB的文檔大小限制(儘管如此,如果您使用這種結構追蹤用戶推薦數量(可能達到數百萬人),而不是美國城市(根據最新的美國人口普查數據超過26,000),我只能看到這種情況。


參考文獻:

http://www.mongodb.org/display/DOCS/Schema+Design

http://www.census.gov/geo/www/gazetteer/places2k.html

+0

謝謝@Caleb!這真的幫助我。有趣的是,我剛剛在2天前回到了這個項目,然後你回答了。 – IamIC 2012-03-11 15:09:10

+0

對我來說,地理是解決這個問題的好方法。 – IamIC 2012-03-11 15:34:24

+0

啊哈,原本你寫過,你想避免地理......我想你是用它的類別和產品,這是這種結構最常見的情況。 :) – 2012-03-15 07:38:34

2

請注意,這個問題也被問到谷歌組。對於這種討論見http://groups.google.com/group/mongodb-user/browse_thread/thread/5cd5edd549813148

一個選項是使用數組鍵。您可以將層次結構存儲爲 值數組(例如['US','CA','Los Angeles'])。然後,你可以基於陣列的關鍵 在各個元素例如對記錄 查詢: 首先,存儲一些文件與代表 層次結構中的數組值

> db.hierarchical.save({ location: ['US','CA','LA'], name: 'foo'}) 
> db.hierarchical.save({ location: ['US','CA','SF'], name: 'bar'}) 
> db.hierarchical.save({ location: ['US','MA','BOS'], name: 'baz'}) 

確保我們在場上的位置索引所以我們可以在加州

0123針對其值執行 快速查詢

> db.hierarchical.ensureIndex({'location':1}) 

查找所有記錄

查找所有記錄在馬薩諸塞州

> db.hierarchical.find({location: 'MA'}) 
{ "_id" : ObjectId("4d9f6a21f88aea89d1492c5a"), "location" : [ "US", "MA", "BOS" ], "name" : "baz" } 

在美國找到的所有記錄

> db.hierarchical.find({location: 'US'}) 
{ "_id" : ObjectId("4d9f69cbf88aea89d1492c55"), "location" : [ "US", "CA", "LA" ], "name" : "foo" } 
{ "_id" : ObjectId("4d9f69dcf88aea89d1492c56"), "location" : [ "US", "CA", "SF" ], "name" : "bar" } 
{ "_id" : ObjectId("4d9f6a21f88aea89d1492c5a"), "location" : [ "US", "MA", "BOS" ], "name" : "baz" } 

注意,在這種模式下,您的數組中值將需要 獨特。例如,如果你在不同的州有'springfield', 那麼你需要做一些額外的工作來區分。

> db.hierarchical.save({location:['US','MA','Springfield'], name: 'one' }) 
> db.hierarchical.save({location:['US','IL','Springfield'], name: 'two' }) 
> db.hierarchical.find({location: 'Springfield'}) 
{ "_id" : ObjectId("4d9f6b7cf88aea89d1492c5b"), "location" : [ "US", "MA", "Springfield"], "name" : "one" } 
{ "_id" : ObjectId("4d9f6b86f88aea89d1492c5c"), "location" : [ "US", "IL", "Springfield"], "name" : "two" } 

您可以通過使用$所有運營商和指定更多 水平層次的克服這一點。例如:

> db.hierarchical.find({location: { $all : ['US','MA','Springfield']} }) 
{ "_id" : ObjectId("4d9f6b7cf88aea89d1492c5b"), "location" : [ "US", "MA", "Springfield"], "name" : "one" } 
> db.hierarchical.find({location: { $all : ['US','IL','Springfield']} }) 
{ "_id" : ObjectId("4d9f6b86f88aea89d1492c5c"), "location" : [ "US", "IL", "Springfield"], "name" : "two" } 
+0

謝謝;我明白你所展示的。但是,如何得到「給我所有映射到Springfield | MA | US的供應商」的結果? (|是二元OR,給我們一個聯合)。 – IamIC 2011-04-09 04:55:05

+0

是不是隻是db.hierarchicla.find({location:'US'})? MA和Springfield是子集,因此不需要OR或union。 – jared 2011-04-09 21:35:30

+0

不需要看看我添加到問題的示例。 – IamIC 2011-04-10 07:24:35