MongoDBでデータを結合する方法

7200 ワード

MongoDB 現代のアプリケーションの最も人気のあるデータベースの一つです.これは、従来のSQLデータベースよりもデータモデリングにより柔軟なアプローチを可能にします.開発者は、この柔軟性のためにより迅速にアプリケーションを構築することができますし、また、オープンソースコミュニティ版にクラウドMongoDBアトラス提供から、複数の展開オプションを持っている.
MongoDBはフィールドを持つドキュメントとして各レコードを格納します.これらのフィールドは、柔軟な型の範囲を持つことができますし、値として他のドキュメントを持つことができます.各ドキュメントはコレクションの一部です-リレーショナルパラダイムから来ている場合、テーブルを考えてください.まだ存在しないグループでドキュメントを作成しようとしている場合、MongoDBはそれをオンザフライで作成します.コレクションを作成し、データを追加する前にスキーマを準備する必要はありません.
MongoDBはMongoDBのクエリ言語を提供しています.ドキュメントのコレクションからデータを取得するとき、我々はフィールドによって検索することができます、我々は期待するすべての方法でフィルタとソート結果を適用します.さらに、ほとんどの言語は、RubyのJavaScriptとMongoidのマングースのようなネイティブオブジェクト関係マッピングを持っています.
返されたデータへの他のコレクションからの関連情報の追加は、常に高速または直感的ではありません.私たちは2つのコレクション:ユーザーのコレクションと製品のコレクションを想像してください.我々はすべてのユーザーのリストを取得し、それぞれが購入した製品のリストを表示したい.我々は、コードを単純化して、クライアントとデータベースの間でデータ取引を減らすために一つの問合せでこれをしたいです.
SQLデータベースにユーザーと製品テーブルの左側の外部結合を使用します.しかし、MongoDBはSQLデータベースではありません.しかし、これはデータの結合を実行することが不可能であることを意味しません.彼らはちょうどSQLデータベースよりわずかに異なっているように見えます.本稿では、我々はMongoDBのデータに参加するための戦略をレビューします.

MongoDBにおけるデータの結合


MongoDBのデータにどのように参加できるかを議論しましょう.結合を行うには2つの方法があります$lookup 演算子と微分異常この記事の後半では、データの結合を行うための代替案も見ます.

$ lookup演算子の使用


MongoDBのバージョン3.2では、データベースクエリ言語$lookup operator . MongoDBのルックアップはaggregation pipeline . この演算子は、同じデータベースにある2つのコレクションに参加できます.それは効果的にデータ収集プロセスにもう一つのステージを加えます.そして、要素が結合されたコレクションから一致するドキュメントである新しい配列フィールドをつくります.以下のようになります.
MongoDBのバージョン3.2では、データベースクエリ言語$lookup 演算子.MongoDBのルックアップは、集約パイプラインのステージとして発生します.この演算子は、同じデータベースにある2つのコレクションに参加できます.それは効果的にデータ収集プロセスにもう一つのステージを加えます.そして、要素が結合されたコレクションから一致するドキュメントである新しい配列フィールドをつくります.以下のようになります.
db.users.aggregate([{$lookup: 
    {
     from: "products", 
     localField: "product_id", 
     foreignField: "_id", 
     as: "products"
    }
}])

あなたは、我々が使用したのを見ることができます$lookup 演算子集合中の演算子.演算子はSQLデータベースで動作している人のための典型的な値を持つオプションオブジェクトを受け取ります.それでfrom 同じデータベースになければならないコレクションの名前ですlocalField 我々が比較する分野はforeignField ターゲットデータベースで.すべてのマッチング製品があると、プロパティによって指定された配列に追加されます.
この方法は、以下のようになります.
SELECT *, products
FROM users
WHERE products in (
  SELECT *
  FROM products
  WHERE id = users.product_id
);

このように、左の結合を使用します.
SELECT *
FROM users
LEFT JOIN products
ON user.product_id = products._id

この操作はしばしば我々のニーズを満たすことができます$lookup 演算子はいくつかの欠点を導入します.第一に、我々が使用する問い合わせのどの段階においても重要である$lookup . これは、多段集約パイプラインの後段において、より複雑なソート、フィルタ、または組み合わせを構築することに挑戦することができる.第二に$lookup は比較的遅い動作であり、問い合わせ時間を増やす.内部の単一のクエリを送信している間、MongoDBはリクエストを満たすために複数のクエリを実行します.

MongoDBにおける逆正規化の使用


を使う代わりに$lookup 演算子は、我々のデータを取り消すことができます.このアプローチは、しばしば同じクエリに対して複数の結合を行う場合に有利です.乱雑化はSQLデータベースで一般的です.たとえば、SQLデータベースに結合されたデータを格納するための隣接テーブルを作成できます.
dengomalizationはmongodbで似ています.このデータを平らなテーブルとして保存するのではなく、すべての結合の結果を表すネストされたドキュメントを持つことができます.このアプローチはMongoDBの豊富な文書の柔軟性を利用する.そして、我々は自由に我々のアプリケーションの意味をなすどのような方法でデータを格納することです.
たとえば、製品、注文、および顧客のための別のMongoDBコレクションを想像してください.これらのコレクションのドキュメントは次のようになります.
製品
{
    "_id": 3,
    "name": "45' Yacht",
    "price": "250000",
    "description": "A luxurious oceangoing yacht."
}

顧客
{
    "_id": 47,
    "name": "John Q. Millionaire",
    "address": "1947 Mt. Olympus Dr.",
    "city": "Los Angeles",
    "state": "CA",
    "zip": "90046"
}

順序
{
    "_id": 49854,
    "product_id": 3,
    "customer_id": 47,
    "quantity": 3,
    "notes": "Three 45' Yachts for John Q. Millionaire. One for the east coast, one for the west coast, one for the Mediterranean".
}

これらのドキュメントを解析して、単一のクエリですべてのデータを取得することができます.
{
    "_id": 49854,
    "product": {
        "name": "45' Yacht",
        "price": "250000",
        "description": "A luxurious oceangoing yacht."
    },
    "customer": {
        "name": "John Q. Millionaire",
        "address": "1947 Mt. Olympus Dr.",
        "city": "Los Angeles",
        "state": "CA",
        "zip": "90046"
    },
    "quantity": 3,
    "notes": "Three 45' Yachts for John Q. Millionaire. One for the east coast, one for the west coast, one for the Mediterranean".
}

このメソッドは実際には、データの書き込み中に、トップレベルのドキュメントに必要なすべてのデータを格納するために動作します.この場合、注文ドキュメントに製品と顧客データをマージしました.我々が現在情報を照会するとき、我々はすぐにそれを得ます.我々のデータを取得するために任意の二次または三次クエリを必要としません.このアプローチは、データ読み出し動作の速度および効率を増加させる.トレードオフは、付加的なupfront処理を必要として、各々の書込み操作のためにされる時間を増やすということである.
製品とその製品を購入するすべてのユーザーのコピーは、追加の課題が存在する.小さなアプリケーションでは、このレベルのデータ複製は問題にはならない.ビジネスの電子商取引のアプリは、各顧客の注文数千人を持って、このデータの複製はすぐに時間とストレージで高価になることができます.
それらの入れ子にされたドキュメントは関係していません.製品に変更がある場合は、すべての製品のインスタンスを検索して更新する必要があります.これは効果的に、我々は変更がそれに影響を与えるかどうかの時間の前に知らないので、コレクション内の各ドキュメントをチェックする必要があることを意味します.

MongoDBの結合に代わるもの


最終的に、SQLデータベースはMongoDBより良い結合を扱います.我々自身がよく手を伸ばすならば$lookup または、正規化されたデータセットでは、ジョブの適切なツールを使用しているかどうか疑問に思うかもしれません.我々のアプリケーションのためのMongoDBを活用する別の方法がありますか?我々のニーズに役立つかもしれない結合を成し遂げる方法が、ありますか?
MongoDBを完全に放棄するのではなく、別の解決策を探すことができた.つの可能性は、MongoDBと同期し、解析のために最適化されている二次索引解決ソリューションを使用することです.例えば、私たちはRockset , エーreal-time analytics データベースは、MongoDBの変更ストリームから直接摂取するには、我々は身近なSQLの検索、集約、結合クエリを使用してデータを照会することができます.

結論


複数のコレクションから関連する要素を結合することによって、豊かなデータセットを作成するためのオプションの範囲があります.最初のメソッドは$lookup 演算子.この信頼できるツールによって、私たちのMongoDBデータに関して左の結合の同等をすることができます.または、我々は我々が必要とする問合せの速い検索を許す非正規化コレクションを準備することができます.これらのオプションの代わりに、私たちはemploy Rockset’s SQL analytics capabilities on data in MongoDB , どのように構造化に関係なく.
あなたはまだROCKSETのリアルタイム分析機能を試していない場合は、なぜ行かない?ドキュメントにジャンプし、どのように使用できるかについての詳細を学ぶRockset with MongoDB .
Rocksetreal-time analytics 現代のデータチームのための雲のデータベース.より低いコストで、ブルートフォース走査のインデックスを利用することによって、より新鮮なデータのより速い分析を得てください.