2017-07-18 19 views
1

ジョインとMongoDBに関して多くの質問がありますが、Mongo 3.xの後で機能を使用しない古い回答が多くあります。私の質問は、どのようにリンクされた要素の条件でテーブルをクエリするでしょうか?ここで複数のジョインに基づくMongoDBクエリ

は非常に単純化した例である

const Person = new mongoose.Schema({ 
    gender: String 
}); 

const Dog = new mongoose.Schema({ 
    breed: String 
}); 

const Team = new mongoose.Schema({ 
    trainer: { 
     type: mongoose.Schema.ObjectId, 
     ref: 'Person' 
    }, 
    members: [{ 
     type: mongoose.Schema.ObjectId, 
     ref: 'Dog' 
    }] 
}) 

これは生産にすでに存在すると、スキーマを変更する可能性はない想像してみてください。私はトレーナーの性別は「男」ある「プードル」品種との少なくとも1匹のメンバーの犬と一緒にすべてのチームを取得する可能性がどのように

答えて

2

質問を別の方法で入力する:mongoDBで2つ以上のコレクションを結合するにはどうすればいいですか?私たちは、集約パイプラインで

Dog.aggregate([{ 
     $match: { 
      breed: "Poodle" 
     } 
    }, 
    { 
     $lookup: { 
      from: "teams", 
      localField: "_id", 
      foreignField: "members", 
      as: "team" 
     } 
    }, 
    { 
     $unwind: "$team" 
    }, 
    { 
     $lookup: { 
      from: "people", 
      localField: "team.trainer", 
      foreignField: "_id", 
      as: "trainer" 
     } 
    }, 

    { 
     $unwind: "$trainer" 
    }, 

    { 
     $match: { 
      "trainer.gender": "male" 
     } 
    }, 
    { 
     $project: { 
      breed: 1, 
      trainer: 1, 
      team: { 
       _id: 1 
      } 
     } 
    } 
], function(err, teams) { 
    console.log(teams) 
}); 

:モデル名に対するあなたのコレクション名を想定し

dogsteamspeople(複数形のマングース大会)あり、次は、所望の結果を達成するための方法の一つであります次

  1. を使用してその後の出発点としてDogを取ると品種
  2. と一致チームと結果を結合し、 "プードル"へのメンバー参照を含むチームを取得します
  3. 2の結果セットにチームの配列が含まれます($ lookupの下のすべてのステップを削除して結果の状態を確認できます)。この配列を別のドキュメントに分割するには、$unwind演算子を使用します(たとえば3つの要素のチームは、親フィールドがすべて複製された3つのドキュメントになります)。
  4. 新しい結果セットで、これは人々をトレーナー配列に置きます。
  5. 再びトレーナー
  6. マッチにあなたが

が必要trainer.gender「男性」

  • $project(選択)フィールドは、最終的な結果は次のようになりますため、結果セットに分割するくつろぐ:

    { 
        "_id" : ObjectId("596e5500b5174986059958a8"), 
        "breed" : "Poodle", 
        "team" : { 
         "_id" : ObjectId("596e564fb5174986059958de") 
        }, 
        "trainer" : { 
         "_id" : ObjectId("596e54bfb51749860599589c"), 
         "gender" : "male" 
        } 
    } 
    
    
    { 
        "_id" : ObjectId("596e5500b5174986059958a8"), 
        "breed" : "Poodle", 
        "team" : { 
         "_id" : ObjectId("596e564fb5174986059958e6") 
        }, 
        "trainer" : { 
         "_id" : ObjectId("596e54bfb51749860599589c"), 
         "gender" : "male" 
        } 
    } 
    
    
    { 
        "_id" : ObjectId("596e5500b5174986059958b2"), 
        "breed" : "Poodle", 
        "team" : { 
         "_id" : ObjectId("596e564fb5174986059958de") 
        }, 
        "trainer" : { 
         "_id" : ObjectId("596e54bfb51749860599589c"), 
         "gender" : "male" 
        } 
    } 
    
    
    { 
        "_id" : ObjectId("596e5500b5174986059958b2"), 
        "breed" : "Poodle", 
        "team" : { 
         "_id" : ObjectId("596e564fb5174986059958e6") 
        }, 
        "trainer" : { 
         "_id" : ObjectId("596e54bfb51749860599589c"), 
         "gender" : "male" 
        } 
    } 
    

    本質的に、我々はDogを検索し、途中で多くのコレクションに参加して一致させました。最終的な文書のルート_idは犬のチームではないので、結果セットにはチームとトレーナーを含む犬が含まれていますが、チームのドキュメントとみなすことができます。あなたはPersonから始まり、Dogに到達することができます。

    また、結果の構造は完全ではありません。母集団teamsには、trainermembersが埋め込まれているため、よく構造化されたフォーマットが必要です。集約パイプラインのいくつかの調整を行うことで、うまく形成された構造が実現できると確信しています。

    最後に、これは別の回答で示唆されているモンゴース人口とは異なります。主な違いは、この場合、必要な文書をmongoサーバーに配置する作業を委任していることです。人口では、クライアントサイドの処理があまりにも多く、dbへの要求が多くなります。しかし、$lookupは、集団を好むかもしれないし、this答えを検討するかもしれない非武装集会で働いています。

  • +1

    私が提案したものよりずっと優れています:) – robertklep

    関連する問題