11

SQL Server と PostgreSQL で行う方法を考え出した特定のデータ操作要件があります。ただ、速度があまりよろしくないのでMongoDBを調べています。

クエリを説明する最良の方法は次のとおりです。米国の階層データを想像してみてください: 国、州、郡、市。特定のベンダーがカリフォルニア全体にサービスを提供できるとしましょう。別のサービスは、おそらくロサンゼルスのみにサービスを提供できます。数十万のベンダーが存在する可能性があり、それらはすべて、この階層のいくつかのポイントからサービスを提供できます。これを Geo と混同しているわけではありません。必要性を説明するためにこれを使用しています。

再帰クエリを使用すると、特定のユーザーにサービスを提供できるすべてのベンダーのリストを簡単に取得できます。たとえば、彼がカリフォルニア州ロサンゼルスのパサデナにいる場合、階層を上って該当する ID を取得してから、下に戻ってベンダーを見つけます。

これは最適化できることを知っています。繰り返しますが、これは単純なクエリの例です。

MongoDB がドキュメント ストアであることは知っています。それは私が持っている他のニーズに非常によく合います。問題は、私が説明するクエリの種類にどれだけ適しているかということです。(結合がないことは知っています-それらはシミュレートされています)。

これは「ひもの長さ」の問題だと思います。MongoDB でこの種のことを行った経験があるかどうかを知りたいだけです。ゼロからテストするまでにはかなりの時間がかかる可能性があり、MongoDB がこれに適していない場合は、時間を節約したいと考えています。

地元の映画店「A」は、スプリングフィールドでブルーレイを供給できます。州全体に流通しているチェーン ストア「B」は、イリノイ州のすべてにブルーレイを供給できます。また、ダウンロード オンデマンド ストア「C」は、米国全土に供給できます。

イリノイ州スプリングフィールドで該当するすべての映画サプライヤーを取得したい場合、答えは [A、B、C] になります。

つまり、階層のさまざまなレベルに多数のベンダーが関連付けられています。

4

2 に答える 2

10

この質問がほぼ 1 年前に出されたことは承知していますが、それ以来、MongoDB はこの問題に対して公式にサポートされているソリューションを提供しており、私はそのソリューションを使用しました。こちらのドキュメントを参照してください: https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

あなたの質問に最も近い概念は「部分パス」と呼ばれます。

祖先データを埋め込むのは少し重く感じるかもしれませんが。このアプローチは、MongoDB での問題を解決する最も適切な方法です。私がこれまでに経験した唯一の落とし穴は、これらすべてを 1 つのドキュメントに保存している場合、十分なデータを処理しているときに、現時点で 16MB のドキュメント サイズ制限に達する可能性があることです (ただし、米国の都市 [最新の米国国勢調査によると 26,000 を超える] ではなく、この構造を使用して [数百万に達する可能性がある] ユーザーの紹介を追跡している場合にのみ、これが発生することがわかります)。


参考文献:

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

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


変更:

置き換えられたリンク: http://www.mongodb.org/display/DOCS/Trees+in+MongoDB

于 2012-03-08T20:09:50.710 に答える
2

この質問は google グループでも行われたことに注意してください。その議論については、http: //groups.google.com/group/mongodb-user/browse_thread/thread/5cd5edd549813148を参照してください。

1 つのオプションは、配列キーを使用することです。階層を値の配列として格納できます (['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'} ) 

その値に対して高速なクエリを実行できるように、場所フィールドにインデックスがあることを確認してください

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

このモデルでは、配列内の値は一意である必要があることに注意してください。たとえば、異なる州に「スプリングフィールド」がある場合、区別するために追加の作業を行う必要があります。

> 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" } 
于 2011-04-08T20:18:00.030 に答える