最初に決定したいのは、正確にどの種類の木を使用するかです。
考慮すべき重要なことは、データとアクセスパターンです。すべての作業の90%がクエリであり、その音(eコマース)による更新は管理者によってのみ実行されると既に述べていますが、ほとんどの場合、めったにありません。
したがって、パスを介して子供にすばやくクエリを実行できるスキーマが必要です。つまり、スポーツ->バスケットボール->男子、スポーツ->テニス->女子であり、実際に更新に合わせてスケーリングする必要はありません。
ご指摘のとおり、MongoDBにはこのための優れたドキュメントページがあります: https://docs.mongodb.com/manual/applications/data-models-tree-structures/ これにより、10genは実際にツリーのさまざまなモデルとスキーマメソッドを記述し、それらの主な浮き沈みを説明します。
簡単にクエリを実行する場合に注意が必要なのは、マテリアライズドパスです。 https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/
これは、ツリーを構築するための非常に興味深い方法です。上記の例を「テニス」の「女性」にクエリするには、事前に固定された正規表現を実行するだけで済みます(インデックスを使用できます: http://docs.mongodb.org/manual/reference/operator/regex/ )そのように:
db.products.find({category: /^Sports,Tennis,Womens[,]/})
ツリーの特定のパスの下にリストされているすべての製品を検索します。
残念ながら、このモデルは更新が非常に苦手です。カテゴリを移動したり、名前を変更したりすると、すべての製品を更新する必要があり、1つのカテゴリに数千の製品が存在する可能性があります。
より良い方法は、cat_id
を格納することです。 製品上で、スキーマを使用してカテゴリを別のコレクションに分割します:
{
_id: ObjectId(),
name: 'Women\'s',
path: 'Sports,Tennis,Womens',
normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}
したがって、クエリにはカテゴリコレクションのみが含まれるため、カテゴリがはるかに小さくなり、パフォーマンスが向上します。これの例外は、カテゴリを削除した場合でも、製品に触れる必要がある場合です。
したがって、「テニス」を「バドミン」に変更する例:
db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
doc.path = doc.path.replace(/,Tennis/, ",Badmin");
db.categories.save(doc);
});
残念ながら、MongoDBは現時点ではクエリ内のドキュメントの反映を提供していないため、クライアント側でそれらを引き出す必要があります。これは少し面倒ですが、多くのカテゴリが戻されることはないはずです。
そして、これは基本的にそれが実際にどのように機能するかです。更新するのは少し面倒ですが、インデックスを使用して任意のパスで即座にクエリを実行できる能力は、私が信じるシナリオにより適しています。
もちろん、追加の利点は、このスキーマが入れ子集合モデルと互換性があることです。 http://en.wikipedia .org / wiki / Nested_set_model たとえば、テニスは「スポーツ」と「レジャー」の両方に分類され、ユーザーの出身地に応じて複数のパスが必要になる場合があります。
マテリアライズドパスのスキーマは、別のpath
を追加するだけで、これを簡単にサポートします。 、その単純な。
それが理にかなっていることを願っています、そこにはかなり長いものがあります。