2017-06-22 9 views
0
db.chat.find().pretty().limit(3) 
{ 
    "_id" : ObjectId("593921425ccc8150f35e7662"), 
    "user1" : 1, 
    "user2" : 2, 
    "messages" : [ 
     { 
      "capty" : 'A', 
      "body" : "hiii 0" 
     }, 
     { 
      "capty" : 'B', 
      "body" : "hiii 1" 
     }, 
     { 
      "capty" : 'A', 
      "body" : "hiii 2" 
     } 
    ] 
} 
{ 
    "_id" : ObjectId("593921425ccc8150f35e7663"), 
    "user1" : 1, 
    "user2" : 3, 
    "messages" : [ 
     { 
      "capty" : 'A', 
      "body" : "hiii 0" 
     }, 
     { 
      "capty" : 'A', 
      "body" : "hiii 1" 
     }, 
     { 
      "capty" : 'B', 
      "body" : "hiii 23" 
     } 
    ] 
} 
{ 
    "_id" : ObjectId("593921425ccc8150f35e7664"), 
    "user1" : 1, 
    "user2" : 4, 
    "messages" : [ 
     { 
      "capty" : 'A', 
      "body" : "hiii 0" 
     }, 
     { 
      "capty" : 'B', 
      "body" : "hiii 1" 
     }, 
     { 
      "capty" : 'B', 
      "body" : "hiii 24" 
     } 
    ] 
} 

私はuser2と本文のuser1 = 1とlast capty = 'B'のリストを得ることができます。すなわち、出力は最後の2行でなければなりません。最後の配列値のクエリ

、つまり望ましい出力。

user2:3, "body" : "hiii 23" 
user2:4, "body" : "hiii 24" 

答えて

0

ここでの主なものは、配列から最後の要素を取得するための集約$sliceで、

db.chat.aggregate([ 
{ "$match": { "user1": 1, "messages.capty": "B" } }, 
{ "$redact": { 
    "$cond": { 
    "if": { 
     "$eq": [ { "$slice": [ "$messages.capty", -1 ] }, ["B"] ] 
    }, 
    "then": "$$KEEP", 
    "else": "$$PRUNE" 
    } 
}}, 
{ "$project": { 
    "user2": 1, 
    "body": { 
    "$arrayElemAt": [ 
     { "$map": { 
     "input": { 
      "$filter": { 
      "input": { "$slice": [ "$messages",-1 ] }, 
      "as": "m", 
      "cond": { "$eq": [ "$$m.capty", "B" ] } 
      } 
     }, 
     "as": "m", 
     "in": "$$m.body" 
     }}, 
     0 
    ] 
    } 
}} 
]) 

私は実際に$filter$project段階で「余分安全」であるが、それがすべてです基本的に同じ。

最初にクエリでドキュメントが選択されていますが、実際にはこの時点では配列の最後の要素と「一致する」とは言えませんが、配列上に条件がまったくないドキュメントをフィルタしたいとします。

$redactは実際のもので、最後の配列エントリを調べ、フィールドの値をテストします。 $messages.captyによって配列からフィールドだけを取り出すことができます。この配列はこれらのアイテムの配列を返します。ここでは、$slice、またはのインデックスである最後の値を取得する場合は$arrayElemAtです。

この時点では、条件に一致しない「文書」のみを「フィルタリング」しました。最後の$projectステージは配列の最後の要素をとり、それが条件(前の段階ですべきである)と一致することを確認し、"body"の値を抽出し、単一配列の内容を単純な値に変換します。

あなたが交互に「慎重」を見送ると$redactはそれが仕事だ行っているはずなので、単純に最後の配列要素をつかむことができます。

db.chat.aggregate([ 
{ "$match": { "user1": 1, "messages.capty": "B" } }, 
{ "$redact": { 
    "$cond": { 
    "if": { 
     "$eq": [ { "$arrayElemAt": [ "$messages.capty", -1 ] }, "B" ] 
    }, 
    "then": "$$KEEP", 
    "else": "$$PRUNE" 
    } 
}}, 
{ "$project": { 
    "user2": 1, 
    "body": { 
    "$arrayElemAt": [ "$messages.body", -1 ] 
    } 
}} 
]) 

全体の事は本当に「と可能文書を一致させるために分解しクエリ "を実行し、最後に" $sliceまたは$arrayElemAt "という要素を比較して抽出します。

結果は以下のとおりです。

{ 
     "_id" : ObjectId("593921425ccc8150f35e7663"), 
     "user2" : 3, 
     "body" : "hiii 23" 
} 
{ 
     "_id" : ObjectId("593921425ccc8150f35e7664"), 
     "user2" : 4, 
     "body" : "hiii 24" 
} 
+0

素敵な、について説明が、すでにやった@QuizMaster –

+0

:-)構文エラーを修正してください。申し訳ありませんが、ラップトップにはメルトダウンがあり、数分かかりました。 –

+0

さんしが友達になりました:-) –

関連する問題