web-dev-qa-db-ja.com

Uberのようなアプリケーション用にMongoDBデータベースを効率的に設計するにはどうすればよいですか?

私はUberのようなアプリケーション用にMongoDBデータベースを設計していますが、NoSQLの概念が初めてなので、いくつか疑問があります。

私は3つの主要なコレクション-ユーザー、リクエスト、メッセージを持っています。ユーザーは配車リクエストを投稿できます。他のユーザーが配車を希望する場合は、そのようなリクエストを受け入れ、2人のユーザー間のテキスト通信が開始されます。

したがって、SQLの世界では、次のテーブルを使用します。

USERS
user_id
username

REQUESTS
request_id
request_details
gps_location
passenger_id
driver_id
timestamp

MESSAGES
message_id
message_body
request_id
sender_id
timestamp

しかし、今はNoSQLの現実にあり、ここでは状況が少し異なる傾向があります。 SQLの考え方、JOINを忘れて、埋め込みドキュメントに慣れる必要があることはわかっています。

問題は、この場合のデータベースを設計する適切な方法は何ですか?

もちろん、私はそのようなデザインを持つことができました:

USERS
{
    "user_id": "001",
    "username": "John"
}

REQUESTS
{
    "request_id": "001",
    "request_details": "Chicago - NYC",
    "gps_location": [21.0,42.0],
    "passenger_username": "John",
    "driver_username": "Claire",
    "timestamp": "30-Mar-2016"
}

しかし、データの冗長性があります-乗客と運転手のユーザー名はユーザーとリクエストの両方のモデルに存在し、ユーザー名が変更された場合は、指定されたユーザーのすべてのリクエストを更新する必要があります。ユーザー名の代わりにuser_idを使用することは解決策になる可能性がありますが、JOINが必要になるため、NoSQLでは回避しようとしています。そして、まだメッセージが残っています-それらをリクエストに効率的に関連付けるにはどうすればよいですか?私はそれが適切な方法ではないと思います、そして私は他に何かが必要です...

だから、おそらくそのようなデザインですか?

{
    "user_id": "001",
    "username": "John",
    "requests": [{
        "request_id": "001",
        "request_details": "Chicago - NYC",
        "gps_location": [21.0,42.0],
        "passenger_username": "John",
        "driver_username": "Claire",
        "timestamp": "30-Mar-2016",
        "messages": [{
            "message_id": "001",
            "message_body": "Hi, how are you?",
            "timestamp": "30-Mar-2016-14-30-00"
        }]
    }]
}

しかし今、他にもいくつかのことが頭に浮かびました。特定の範囲内で、特定のタイムスパン内でリクエストを検索する必要があることがよくあります。 「24時間以内に10マイル以内にあるすべてのリクエストを表示する」、そしてそのようなリクエストについては、そのすべての詳細とそれを投稿したユーザーのユーザー名を表示する必要があります。実際、私はユーザーよりも頻繁にリクエストを求めます(各ユーザーにはより多くの情報があり、IDと名前だけでなく、google/facebookのユーザー名、写真、電話番号なども含まれます)。このデザインに問題はありませんか?

これらすべてのコレクション(ユーザー/リクエスト/メッセージ)が互いに結合しすぎていませんか?

ここでデータベースを設計する最良の方法は何でしょうか?

1
CorrieSparrow

質問で示したように、データには明確な関係構造があります。

  • さまざまなオブジェクト(ユーザー、リクエスト、メッセージ)があり、それらはすべて相互に関連付けられています
  • これらのオブジェクトには、他のオブジェクト(リクエスト)から何度も参照される属性(例:ドライバーや乗客の名前)があります。これには、データの複製または正規化(したがって結合)が必要です
  • さまざまなオブジェクトは互いに密接に結合されており、予想されるデータアクセスパターンは複数の角度からクエリを実行する必要性を反映しています。

この記事のタイトルは意図的に挑発的ですが、多くの優れたコンテンツがあります。 MongoDBを使用してはならない理由

特に、「MongoDBがデータを格納する方法」セクションとその後のいくつかのセクションでは、正規化と非正規化に関して尋ねる質問と、データを効率的にクエリする方法に関する問題について詳しく説明しています。

結局のところ、主な質問が1つあります。

ここでデータベースを設計する最良の方法は何でしょうか?

答えは:データはリレーショナルなので、MongoDBを使用しないでください。

MongoDBは、アプリケーションに関連する構造化されていない(または構造化されていない)データを格納するための適切なソリューションである可能性がありますが、特定のデータについては、それは間違った選択です。

2
AMtwo