2017-02-08 14 views
12

私は初心者です。しかし、私はクエリを書くための最も論理的な方法を学ぼうとしています。2つの異なるフィールドで値を検索するmongodb + node.js

私は次のようなコレクションを持っているとします。

{ 
    "id" : NumberInt(1), 
    "school" : [ 
     { 
      "name" : "george", 
      "code" : "01" 
     }, 
     { 
      "name" : "michelangelo", 
      "code" : "01" 
     } 
    ], 
    "enrolledStudents" : [ 
     { 
      "userName" : "elisabeth", 
      "code" : NumberInt(21) 
     } 
    ] 
} 
{ 
    "id" : NumberInt(2), 
    "school" : [ 
     { 
      "name" : "leonarda da vinci", 
      "code" : "01" 
     } 
    ], 
    "enrolledStudents" : [ 
     { 
      "userName" : "michelangelo", 
      "code" : NumberInt(25) 
     } 
    ] 
} 

私はそれらに対応するcode値でkeyの発生を一覧表示します。一例として、key

:キーの発生を検索するにmichelangelo

、私はように2つのdifferen aggregationクエリを書きました。

db.test.aggregate([ 
    {$unwind: "$school"}, 
    {$match : {"school.name" : "michelangelo"}}, 
    {$project: {_id: "$id", "key" : "$school.name", "code" : "$school.code"}} 
]) 

db.test.aggregate([ 
    {$unwind: "$enrolledStudents"}, 
    {$match : {"enrolledStudents.userName" : "michelangelo"}}, 
    {$project: {_id: "$id", "key" : "$enrolledStudents.userName", "code" : "$enrolledStudents.code"}} 
]) 

これら2つのクエリの結果は、私が欲しいものとして返します。それらの

{ "_id" : 1, "key" : "michelangelo", "code" : "01" } 
{ "_id" : 2, "key" : "michelangelo", "code" : 25 } 

一つenrolledStudentsで検索するには、他の一つはschoolフィールドで検索されます。

これらの2つのクエリをより論理的なクエリに減らすことはできますか?それともこれが唯一の方法ですか?

ps:私はデータベース構造が論理的ではないことを認識していますが、私はシミュレートしようとしました。

編集 私は検索でクエリを書き込もうとしています。

db.test.find({$or: [{"enrolledStudents.userName" : "michelangelo"} , {"school.name" : "michelangelo"}]}).pretty() 

しかし、これはドキュメント全体を返します。

{ 
    "id" : 1, 
    "school" : [ 
     { 
      "name" : "george", 
      "code" : "01" 
     }, 
     { 
      "name" : "michelangelo", 
      "code" : "01" 
     } 
    ], 
    "enrolledStudents" : [ 
     { 
      "userName" : "elisabeth", 
      "code" : 21 
     } 
    ] 
} 
{ 
    "id" : 2, 
    "school" : [ 
     { 
      "name" : "leonarda da vinci", 
      "code" : "01" 
     } 
    ], 
    "enrolledStudents" : [ 
     { 
      "userName" : "michelangelo", 
      "code" : 25 
     } 
    ] 
} 

答えて

2

モンゴ3.4

$match - このステージは、両方のクエリ条件

$groupに一致する少なくとも1つの埋め込まれた文書が存在し、すべてのschoolアレイとenrolledStudentsを維持する - このステージはすべて結合しますschoolおよびenrolledStudentsは、グループ内の各_idに対して2dの配列に配列します。

$project - この段階では、新しいラベルvalues配列との配列をクエリ条件に合致して$mapためmerge配列を$filterます。

$unwind - この段階では配列が平坦化されます。

$addFields & $replaceRoot - この段階ではidフィールドを追加し、トップにvalues配列を推進していきます。

db.collection.aggregate([ 
    {$match : {$or: [{"enrolledStudents.userName" : "michelangelo"} , {"school.name" : "michelangelo"}]}}, 
    {$group: {_id: "$id", merge : {$push:{$setUnion:["$school", "$enrolledStudents"]}}}}, 
    {$project: { 
     values: { 
       $map: 
       { 
        input: { 
          $filter: { 
           input: {"$arrayElemAt":["$merge",0]}, 
           as: "onef", 
           cond: { 
            $or: [{ 
             $eq: ["$$onef.userName", "michelangelo"] 
            }, { 
             $eq: ["$$onef.name", "michelangelo"] 
            }] 
           } 
          } 
         }, 
        as: "onem", 
        in: { 
         key : { $ifNull: [ "$$onem.userName", "$$onem.name" ] }, 
         code : "$$onem.code"} 
       } 
      } 
     } 
    }, 
    {$unwind: "$values"}, 
    {$addFields:{"values.id":"$_id"}}, 
    {$replaceRoot: { newRoot:"$values"}} 
]) 

サンプル応答

{ "_id" : 2, "key" : "michelangelo", "code" : 25 } 
{ "_id" : 1, "key" : "michelangelo", "code" : "01" } 

Mongoの< = 3.2

応答をフォーマットする$projectと上記集合の最後の2つのステージを交換します。

{$project: {"_id": 0 , id:"$_id", key:"$values.key", code:"$values.code"}} 

サンプル応答

{ "_id" : 2, "key" : "michelangelo", "code" : 25 } 
{ "_id" : 1, "key" : "michelangelo", "code" : "01" } 

代わり$group & match$redactを使用し、応答をフォーマットする$map$projectを追加することができます。

$redact一度に文書レベルを通過し、一致基準で$$DESCEND$$PRUNEを実行する必要があります。

唯一の注意点は、idの最初のドキュメントレベルでの$ifNullの使用です。これにより、さらなる処理のために埋め込みドキュメントレベルに$$DESCENDを含めることができます。

db.collection.aggregate([ 
    { 
     $redact: { 
      $cond: [{ 
       $or: [{ 
        $eq: ["$userName", "michelangelo"] 
       }, { 
        $eq: ["$name", "michelangelo"] 
       }, { 
        $ifNull: ["$id", false] 
       }] 
      }, "$$DESCEND", "$$PRUNE"] 
     } 
    }, 
    { 
     $project: { 
      id:1, 
      values: { 
       $map: 
       { 
        input: {$setUnion:["$school", "$enrolledStudents"]}, 
        as: "onem", 
        in: { 
         key : { $ifNull: [ "$$onem.userName", "$$onem.name" ] }, 
         code : "$$onem.code"} 
       } 
      } 
     } 
    }, 
    {$unwind: "$values"}, 
    {$project: {_id:0,id:"$id", key:"$values.key", code:"$values.code"}} 
]) 
関連する問題