NoSQLデータベースを使用してnode.jsアプリケーションの分類構造(地理用語)を実装したいと思います。 MySQLと同様の分類構造を持っていましたが、先に進んで新しいことを学ぶときが来たので、別のアプローチを試して、テストアプリにNoSQL(ドキュメント指向)を使用することにしました。分類構造は単純です。国(ie英国)→地域(イングランド)→郡(マージーサイド)→都市/の5つのレベルがあります。町/村(リバプール)→都市の一部(トックステス)。
明らかな選択は木の構造を使用することですが、悪魔は詳細にあります-歴史的にいくつかの都市や町は他の郡に属していました。アイデアは、特定の都市や町で生まれた人にそれらの用語をタグ付けし、後でジオタグでフィルタリングすることでした。そのため、リバプールやマンチェスター(とりわけ)が生まれたときにランカシャーの一部であったという事実を尊重する必要があります。そうしないと、ユーザーが私のジオフィルターで取得する結果が正しくなくなります。
例:John Doeは1957年にブラックバーン(ランカシャー)で生まれました。PaulBrownは1960年にリバプール(ランカシャー、現在はマージーサイド)で生まれました。ジョージア・ドー(ニー・ジョーンズ)は、5年後にウィラル(チェシャー、現在はマージーサイド)で生まれました。彼らの息子のリンゴは1982年にリバプール(当時はマージーサイド)で生まれました。
ジョンは生まれつきランカスター朝、ポールはランカスター朝とマージーサイド、ジョージアはチェシャーとマージーサイド、リンゴはマージーサイドです。したがって、郡で検索する場合は、それに応じて分類する必要があります。しかし、国の現代的な構造に従った単純な1対多の構造では、本来あるべきようにフィルタリングされることは決してありません。
NoSQL(まず第一にドキュメント指向)ソリューションでその構造の複雑さを尊重してコレクションを実装するにはどうすればよいですか?私はそれをグーグルで検索し、スタック*について調査しましたが、それでも次に何をすべきかわかりませんでした。私の意見では、それを解決するためのいくつかの可能な方法があります:
SQLのようなデータ構造を使用します。
{
{'name': 'United Kingdom', 'unique_id': 1},
{'name': 'England', 'unique_id': 2, 'parents': [1]},
{'name': 'Merseyside', 'unique_id': 3, 'parents': [2]},
{'name': 'Lancashire', 'unique_id': 4, 'parents': [2]},
{'name': 'Liverpool', 'unique_id': 5, 'parents': [3, 4]},
}
いくつかの参照とともにツリー構造を使用します。
{
{'name': 'United Kingdom', 'unique_id': 1
{'name': 'England', 'unique_id': 2]
{'name': 'Merseyside', 'unique_id': 3]
{'name': 'Liverpool', 'unique_id': 5, 'alternate_parents': [4]},
},
{'name': 'Lancashire', 'unique_id': 4},
},
},
}
参照のないツリー構造(1対多)を使用し、「代替親」タグをドキュメントに手動で追加します。
{
{'name': 'United Kingdom', 'unique_id': 1
{'name': 'England', 'unique_id': 2]
{'name': 'Merseyside', 'unique_id': 3]
{'name': 'Liverpool', 'unique_id': 5},
},
{'name': 'Lancashire', 'unique_id': 4},
},
},
}
SQLに固執します。
その件についてアドバイスをください。私はNoSQLの初心者なので(現在、そのようなデータベースは設計していません)、実際の設計上の問題があります。
そして、私はスタック*に慣れていないので、この投稿で何か問題があった場合は、遠慮なく修正してください:)ありがとうございます!
[〜#〜] edit [〜#〜]解決策として@Jonathanの回答を選択しました。特に@Valentynによって提案されたmapReduce機能を使用すると、私のニーズに適していると思います(データベースに保存し、それらの用語でタグ付けする他のドキュメントがあります)。
ただし、アプリに必要なドキュメントコレクションがない場合は、@ Philippによって提案されたグラフデータベース(ドキュメントではなく関係に基づく)がおそらく最善の解決策です。
まず、基本的な原則に精通していない場合、NoSQLとSQLデータベースのどちらを選択するかは困難です。これが保存している唯一のデータである場合は、リレーショナル(SQL)を使用してください。より多くのデータ(私が推測する)があり、それがより多くの織り交ぜられたスキーマを必要とする場合は、NoSQLの手を下に置いてください。
複雑になりすぎないように、これについてリレーショナルルートを使用します...いくつかのコレクションを開始します。国、地域などに1つ。 NoSQLデータベースでリレーショナル(SQL)タイプのスキーマを実行することを躊躇しないでください。ほとんどの場合、それらは最良の解決策です。
次に、各サブグループに、親を指定するフィールドがあります。
例えば:
{
{'name': 'United Kingdom'},
{'name': 'United States'}
}
{
{'name': 'England', 'parent': 'United Kingdom'},
{'name': 'California', 'parent': 'United States'}
}
そうすれば、返されるデータが管理不能になるほどデータセットがネストされることはありません。次に、国と対応する地域などを簡単に取得できます。
頑張ってください!
編集:OPの質問に答える:
(まず、MongoDBをお勧めします-これはあらゆる面で優れたソリューションです。)
MongoDBを使い始めると、データがハードドライブに並べて保存されていることに気付くでしょう。このような巨大なレコードを編集すると、ディスクの背面にプッシュされる可能性が高くなり、ハードドライブがスイスチーズのようになります。その時点に到達したら、もう一度それを凝縮するために修理を行う必要があります。また、この方法では、アプリケーションでデータをより簡単に分離できます。これにより、データを処理する必要がある場合でも、オブジェクト全体にデータを適用する必要がなくなります。世界にはさまざまな場所があるため、大きなデータセットがあると思います。
そのようなことについてはあまり心配しないでください。名前を頻繁に変更する予定がある場合は、親にIDを使用し、子をIDと一致させることができます。ロケーションデータベースを変更する必要はないと思ったので、この方法で実行しました。
配列ではなく、ネストされたドキュメントを使用して複数の親を格納します。そうすれば、より簡単にクエリとインデックスを作成できます。次の方法を使用します。
{
{
'name': 'England,
'parent': {
1: 1,
568: 1
}
}
}
そうすれば、インデックスのアイデアを採用して、db.region.$.568
= 1
の場所を見つけることができます。
コメントがあるので、「NoSQL」とは「MongoDB」という意味だと思います。一般にNoSQLと呼ばれる、まったく異なるデータベーステクノロジは他にもたくさんありますが、これはあなたが言っているもののようです。
タクソノミーチェーン全体を取得するには、複数のデータベースクエリを実行する必要があるため、これはお勧めできません。これは通常、回避する必要があります。
3. MongoDBにはドキュメントあたり16MBの制限があるため、巨大なツリーである単一のドキュメントもお勧めできません。巨大なモノリシックドキュメントを作成すると、その制限に達する可能性があります。
MongoDBはあなたのユースケースに最適なソリューションではないかもしれないと思います。 グラフデータベース の使用を検討しましたか? MongoDBは、独立した自己完結型のドキュメント用に最適化されています。しかし、グラフデータベースの焦点は、他のエンティティとの関係によって定義されるエンティティが多数あるデータセットにあります。これはあなたのユースケースによく似ています。