2017-07-26 2 views
1

$ lookupを使って2つのコレクションを結合していますが、 'joined'コレクションにフィルタを適用して開始コレクションで投影を使用できます$ redactと$ projectを使用して、いくつかのアプローチを試して、結合されたコレクションのフィルタと投影の両方を組み合わせてください。私は集中的にstackoverflowに見えたが、私はこの組み合わせを見つけることができませんでした。 コレクションメタ:フィルタリングされた検索で特定のフィールドを配列に投影する方法

{ "Exp": "A","test": "OK","date": "3"} 
{ "Exp": "B","test": "OK","date": "5"} 
{ "Exp": "C","test": "Failed","date": "9"} 

コレクションのマージ(結合すべき '): はここで例に来

{ "Exp": "A","M1": "2","M2": "test","T": "1"} 
{ "Exp": "A","M1": "2","M2": "val", "T": "2"} 
{ "Exp": "A","M1": "2", "M2": "val","T": "3"} 
{ "Exp": "B","M1": "1", "M2": "test","M4": "1","T": "1"} 
{ "Exp": "B","M1": "1","M2": "val","M4": "1","T": "2"} 
{ "Exp": "B","M1": "1","M2": "val","M4": "1","T": "3"} 
{ "Exp": "C","M1": "2","M2": "test","M3": "2","T": "1"} 
{ "Exp": "C","M1": "2","M2": "val","M3": "2","T": "2"} 
{ "Exp": "C","M1": "2","M2": "val","M3": "2","T": "3"} 

をし、クエリは次のようになります。参加 'メタ' と '経験' を使用して 'マージ' をmeta.test = "OK"とmerge.M2 = "val"が、meta.Exp、meta.test、およびmerge.M1、merge.M2、およびmerge.Tのみを表示するものだけを選択します。

これは私が得たどのくらいです:

db.meta.aggregate([ 
{ $match: { test: "OK" }}, 
{ $lookup: 
    { from: "merge", 
    localField: "Exp", 
    foreignField: "Exp", 
    as: "kin" 
    } 
}, 
{ $project: 
    { "Exp": true, 
    "test": true, 
    kin : 
    { $filter: 
     { input: "$kin", 
     as: "kin", 
     cond: { $eq: [ "$$kin.M2", "val" ]} 
     } 
    } 
    } 
    } 
]) 

が、フィルタが失敗し続けるとともにmerge.M1、merge.M2、およびmerge.Tに関する追加の突起を含めるしようとしています。結果は次のようになります。

{ "Exp" : "B", 
    "test" : "OK", 
    "kin" : [ 
     { "M1" : "1", 
     "M2" : "val", 
     "T" : "2"}, 
     { "M1" : "1", 
     "M2" : "val", 
     "T" : "3"}] 
} 
{ "Exp" : "A", 
    "test" : "OK", 
    "kin" : [ 
     { "M1" : "2", 
     "M2" : "val", 
     "T" : "2"}, 
     { "M1" : "2", 
     "M2" : "val", 
     "T" : "3"} 
    ] 
} 

ヒントありがとう! ジョルディあなたが返すように、アレイのどのフィールドを指定する$mapを使用

+0

アレイの「フィールド」を制限する場合は、 '$ map'を使い、必要なフィールドだけを明示的にインクルードします。 '$ filter'を' $ map'の '' input "'パラメータとして使うことができます。 –

+0

こんにちは、それを動作させることはできません。例は非常に良いでしょう。 – Jordi

+0

さて、私はあなたのために**ワンステージで解決しました。おそらくあなたは実際にそれを見て何かを学ぶべきです。あなたがそれを求めたからです。 –

答えて

0

あなたのために戻ります
db.meta.aggregate([ 
    { "$match": { test: "OK" }}, 
    { "$lookup":{ 
    "from": "merge", 
    "localField": "Exp", 
    "foreignField": "Exp", 
    "as": "kin" 
    }}, 
    { "$project": { 
    "Exp": 1, 
    "test": 1, 
    "kin": { 
     "$map": { 
     "input": { 
      "$filter": { 
      "input": "$kin", 
      "as": "k", 
      "cond": { "$eq": [ "$$k.M2", "val" ] } 
      } 
     }, 
     "as": "k", 
     "in": { 
      "M1": "$$k.M1", 
      "M2": "$$k.M2", 
      "T": "$$k.T" 
     } 
     } 
    } 
    }} 
]) 

/* 1 */ 
{ 
    "_id" : ObjectId("5979a8857dcd6a5f6a9b4b9a"), 
    "Exp" : "A", 
    "test" : "OK", 
    "kin" : [ 
     { 
      "M1" : "2", 
      "M2" : "val", 
      "T" : "2" 
     }, 
     { 
      "M1" : "2", 
      "M2" : "val", 
      "T" : "3" 
     } 
    ] 
} 

/* 2 */ 
{ 
    "_id" : ObjectId("5979a8857dcd6a5f6a9b4b9b"), 
    "Exp" : "B", 
    "test" : "OK", 
    "kin" : [ 
     { 
      "M1" : "1", 
      "M2" : "val", 
      "T" : "2" 
     }, 
     { 
      "M1" : "1", 
      "M2" : "val", 
      "T" : "3" 
     } 
    ] 
} 
0

colleaqueによって提案された代替の方法は、第二を使用しています$投影。私はこれが$ mapよりも効率的だと考えています。なぜなら、配列の各要素を上回らないからです。トリックは最初の$投影からの投影を繰り返すことです。

db.meta.aggregate([ 
    { $match: { test: "OK" }}, 
    { $lookup: { from: "merge", localField: "Exp", foreignField: "Exp", as: 
    "kin" }}, 
    { $project: 
    { "Exp": true, "test": true, "date": true, 
     kin : { $filter: { input: "$kin", as: "kin", cond: { $eq: [ 
     "$$kin.M2", 
     "val" ]}} 
    } 
    } 
    }, 
    { $project: { 
    "Exp": true, "test": true, "date": true, 
    "kin.M1": true, "kin.M2": true, "kin.T": true } 
    } 
]) 
関連する問題