MongoDB适用于分层类型查询

时间:2011-04-08 19:13:04

标签: mongodb hierarchical-data mongodb-.net-driver

我有一个特定的数据操作要求,我已经解决了如何在SQL Server和PostgreSQL中做的事情。但是,我对速度不太满意,所以我正在调查MongoDB。

描述查询的最佳方法如下。描绘美国的分层数据:国家,州,县,市。假设一个特定的供应商可以为整个加州服务。另一个可能只服务于洛杉矶。可能有数十万个供应商,他们都可以从这个层次结构中的某些点进行服务。我并没有把它与Geo混淆 - 我用它来说明需要。

使用递归查询,可以非常简单地获得可以为特定用户提供服务的所有供应商的列表。如果他在加利福尼亚州洛杉矶的帕萨迪纳说,我们会走上层次结构以获取适用的ID,然后再回头查找供应商。

我知道这可以优化。同样,这只是一个简单的查询示例。

我知道MongoDB是一个文档存储。这非常适合我的其他需求。问题是它对我描述的查询类型有多适合? (我知道它没有连接 - 这些是模拟的)。

我知道这是“一段字符串多长时间”的问题。我只是想知道是否有任何人有使用MongoDB做这种事情的经验。从0开始测试可能需要一段时间,如果MongoDB不适合这个,我希望节省时间。

示例

本地电影商店“A”可以在斯普林菲尔德提供Blu-Rays。具有全州分布的连锁店“B”可以向所有IL提供Blu-Rays。按需下载商店“C”可以供应给所有美国人。

如果我们想要获得伊利诺伊州斯普林菲尔德的所有适用电影供应商,那么答案将是[A,B,C]。

换句话说,在层次结构上有许多不同级别的供应商。

2 个答案:

答案 0 :(得分:8)

我意识到这个问题是在近一年前提出来的,但从那时起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

答案 1 :(得分:2)

请注意,谷歌小组也提出了这个问题。有关该问题,请参阅http://groups.google.com/group/mongodb-user/browse_thread/thread/5cd5edd549813148

一种选择是使用数组键。您可以将层次结构存储为 值数组(例如['US','CA','洛杉矶'])。然后你可以 根据该数组键中的各个元素查询记录 例如:  首先,使用表示的数组值存储一些文档 等级

> 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'} ) 

确保我们在位置字段上有索引,以便我们执行 快速查询其值

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

查找加利福尼亚州的所有记录

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

查找马萨诸塞州的所有记录

> 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" } 

您可以通过使用$ all运算符并指定更多来解决此问题 层次结构的级别。例如:

> 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" }