ドキュメントの配列に格納された2つのアイテムの計算に基づいて、MongoDBからのドキュメントを返すクエリを記述したいとします。配列の最後の値と2番目の最後の値を比較する
この場合、配列内の最後の項目が同じ配列内の最後から2番目の項目未満のすべてのドキュメントを返したいとします。
これはMongoDBでも可能ですか?あなたは正しい方向に私を指すことができますか?
どのポインタも大変感謝しています。
ドキュメントの配列に格納された2つのアイテムの計算に基づいて、MongoDBからのドキュメントを返すクエリを記述したいとします。配列の最後の値と2番目の最後の値を比較する
この場合、配列内の最後の項目が同じ配列内の最後から2番目の項目未満のすべてのドキュメントを返したいとします。
これはMongoDBでも可能ですか?あなたは正しい方向に私を指すことができますか?
どのポインタも大変感謝しています。
MongoDB 3.2をお持ちの場合は、集約フレームワークを使用して基準に一致する文書のIDを取得できます。 IDを取得したら、必要に応じて処理を繰り返すことができます。
例:
db.collection.aggregate([
{$project:{
cond :{$cond:[{
$gt:[{
$slice:["$v", -2,1]
}, {
$slice:["$v", -1,1]
}]
}, true, false]
}}
},
{$match:{cond: true}}
])
私は私のコレクションで文書を次ています
{
"_id" : ObjectId("57094622b08be16cf12fcf6f"),
"v" : [
1.0,
2.0,
3.0,
4.0,
8.0,
7.0
]
}
{
"_id" : ObjectId("5709462bb08be16cf12fcf70"),
"v" : [
1.0,
2.0,
3.0,
4.0,
8.0,
10.0
]
}
をあなたの問題の声明によると、あなたはその最後の要素配列の第二の最後未満の文書を選択したいです、したがって、それは含まれている文書を選択する必要があります_id = ObjectId("57094622b08be16cf12fcf6f")
集計クエリが実行されます。
{
"_id" : ObjectId("57094622b08be16cf12fcf6f"),
"cond" : true
}
これは私たちが望んでいるものです。
上記のとおり、返された情報を反復処理して、完全なドキュメントを取得するなど、任意のアクションを取ることができます。
注:ドキュメントがシンプルな場合は、フィールドを投影することができます。カーソルの反復処理でドキュメント全体を取得する必要はありません。しかし、私の例では、ドキュメントが複雑で、ドキュメントプロパティや属性の初期情報がないと仮定しています。 (上向き3.2)
ここで最良の動作は、アレイからの単一の値を取得する$arrayElemAt
とともに条件に基づいて、「論理フィルタ」を実行$redact
を使用することです。
{ "_id": 1, "data": [1,2,3] },
{ "_id": 2, "data": [3,2,1] }
次にクエリ:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$lt": [
{ "$arrayElemAt": [ "$data", -1 ] },
{ "$arrayElemAt": [ "$data", -2 ] }
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
文書は、アレイメンバー内のサブ文書で「プロパティ」を含む場合、あなただけのために$map
を適用するサンプル考える
比較のために検査するプロパティの値を抽出します。また、$let
の助けを借りて、表現を繰り返す必要はありません。
{
"_id": 1,
"data": [
{ "name": "c", "value": 1 },
{ "name": "b", "value": 2 },
{ "name": "a", "value": 3 }
]
},
{
"_id": 2,
"data": [
{ "name": "a", "value": 3 },
{ "name": "b", "value": 2 },
{ "name": "c", "value": 1 }
]
}
と問合せ::サンプルとして
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$let": {
"vars": {
"data": {
"$map": {
"input": "$data",
"as": "el",
"in": "$$el.value"
}
}
},
"in": {
"$lt": [
{ "$arrayElemAt": [ "$$data", -1 ] },
{ "$arrayElemAt": [ "$$data", -2 ] }
]
}
}
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
「プロパティ」値を比較するときObject
の字句比較は必ずしも条件とは一致しませんので、ここで重要なの取得もう一方の配列要素に渡します。
db.collection.find(function() {
return this.data.pop().value < this.data.pop().value
})
これは、結果を決定するために、JavaScriptの評価を使用し、ネイティブコード化された事業者よりも遅くなるん:MongoDBののか、あなたの代わりに条件を評価するために$where
を使用することができ、代替として、古いバージョンの
集約フレームワークその表現は簡単に書くことができますが、これを行う最も効果的な方法ではありません。
以前のバージョンでは集約フレームワークとは「可能」なのではありません。このプロセスは、アレイを「再グループ化」してから、「次の」$last
要素を取得するために比較をフィルタリングすることによって、配列から$last
要素を取り出すことを含む。
db.collection.aggregate([
// Unwind array
{ "$unwind": "$data" },
// Group back and get $last
{ "$group": {
"_id": "$_id",
"data": { "$push": "$data" },
"lastData": { "$last" "$data" }
}},
// Unwind again
{ "$unwind": "$data" },
// Compare to mark the last element
{ "$project": {
"data": 1,
"lastData": 1,
"seen": { "$eq": [ "$lastData", "$data" ] }
}},
// Filter the previous $last from the list
{ "$match": { "seen": false } },
// Group back and compare values
{ "$group": {
"_id": "$_id",
"data": { "$push": "$data" },
"lastData": { "$last": "$lastData" },
"secondLastData": { "$last": "$data" },
"greater": {
"$last": { "$lt": [ "$data.value", "$lastData.value" ] }
}
}},
// Filter to return only true
{ "$match": { "greater": true } }
])
そして、それは$where
が、この場合、非常にクリーンでよりパフォーマンスであるのに対し、かなり醜いプロセスである:これは、パフォーマンスのために、一般的に非常に良いアイデアではありません。したがって、以前のMongoDBバージョンでのみこれを使用するのは、その条件に一致するデータに対して "さらに"集計操作を実行する必要がある場合です。
ここでは、最新のバージョンを入手し、$redact
を論理的な比較で「シングル」パイプラインステージで使用することができます。各アグリゲーションパイプライン段階では、結果の全体的な処理時間に「コスト」が加算されるため、常により「少ないです」と同じです。