あなたはMongoDBの3.2が利用できる持っているなら、あなたはこのような何か行うことができます。
db.sample.aggregate([
{ "$unwind": "$apdata" },
{ "$group": {
"_id": "$_id",
"apdata": { "$push": "$apdata" },
"max": { "$max": "$apdata.level" }
}},
{ "$unwind": "$apdata" },
{ "$redact": {
"$cond": {
"if": { "$eq": [ "$apdata.level", "$max" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$group": {
"_id": "$apdata.bssid",
"ssid": { "$first": "$apdata.ssid" },
"count": { "$sum": 1 }
}}
])
とのMongoDB 2.4のために:あなたがこれを行う必要があり、少なくともMongoDBの2.6については
db.sample.aggregate([
{ "$project": {
"apdata": {
"$arrayElemAt": [
{ "$filter": {
"input": "$apdata",
"as": "el",
"cond": {
"$eq": [
"$$el.level",
{ "$max": {
"$map": {
"input": "$apdata",
"as": "data",
"in": "$$data.level"
}
}}
]
}
}},
0
]
}
}},
{ "$group": {
"_id": "$apdata.bssid",
"ssid": { "$first": "$apdata.ssid" },
"count": { "$sum": 1 }
}}
])
を2.2このように:
db.sample.aggregate([
{ "$unwind": "$apdata" },
{ "$group": {
"_id": "$_id",
"apdata": { "$push": "$apdata" },
"max": { "$max": "$apdata.level" }
}},
{ "$unwind": "$apdata" },
{ "$project": {
"apdata": 1,
"isMax": { "$eq": [ "$apdata.level", "$max" ] }
}},
{ "$match": { "isMax": true } },
{ "$group": {
"_id": "$apdata.bssid",
"ssid": { "$first": "$apdata.ssid" },
"count": { "$sum": 1 }
}}
])
すべての場合$max
を使用して、各ドキュメントの配列の「最大」値を「最初に」取得してから、$group
で使用する前に配列コンテンツを「フィルタリング」することができます。これに対するアプローチはバージョンによって異なるだけです
MongoDB 3.2:$max
は値の「配列」で直接動作することができます。したがって、$map
は、"level"
の値を取得し、その「最大」が実際に何であるかを調べるために使用されます。
は次いでだけでは「最大」値に一致する配列要素を返すために使用することができ、最終的に$arrayElemAt
はプレーンとして要素「のみ」(「ゼロ」のインデックスのうち二つの可能と)ことを返すために使用され資料。あなたは基本的に_id
と$first
"ssid"
値を取得するために、両方のためにその全体の声明を繰り返し、それが証明するために別途$project
に書くことが少し簡単だ場合
全体のプロセスは、「のみ」$group
で行うことができます。
MongoDB 2.6:これは、特に操作性の高い演算子がなく、特に$max
がアレイ上で「直接」動作する能力が欠けています。注目すべきことは、最初に$unwind
の配列が必要であり、実際にはその最大値を得るために、元の文書の上に実際に$group
だけです。
このプロセスでは、後で配列から要素をグループ化してから$redact
を使用してコンテンツをフィルタ処理するため、実際には$unwind
が必要になります。これは、の「論理的な」形式で、"level"
と、前の段階から計算された「最大」を直接比較することができます。したがって、「最大」でない要素は削除されます。
MongoDB 2。4:$redact
の代わりに実際に$project
物理を必要とする以外は、$match
でフィルタリングに使用するフィールドをドキュメントに入れることを除いて、基本的に同じロジックです。
すべてのバージョンはあなたがグループ化キーの発生をカウントする"ssid"
のためにそのグループの境界とシンプルな$sum
にグループ化キーと$first
結果を"apdata.bssid"
へのパスを指定する同じ最終$group
を、持っています結果。
すべては、次のと同じように返します。
{ "_id" : "f4:b7:e2:56:e4:20", "ssid" : "Test Network2", "count" : 1 }
{ "_id" : "b8:a3:86:67:03:56", "ssid" : "Test Network1", "count" : 2 }
次のように実際のMongoDB 3.2のための最も「効率的な」形式は次のようになります。
db.sample.aggregate([
{ "$group": {
"_id": {
"$arrayElemAt": [
{ "$map": {
"input": {
"$filter": {
"input": "$apdata",
"as": "el",
"cond": {
"$eq": [
"$$el.level",
{ "$max": {
"$map": {
"input": "$apdata",
"as": "data",
"in": "$$data.level"
}
}}
]
}
}
},
"as": "apdata",
"in": {
"bssid": "$$apdata.bssid",
"ssid": "$$apdata.ssid"
}
}},
0
]
},
"count": { "$sum": 1 }
}}
])
をわずかに異なる形で起因します化合物_id
であるが、それは単一の$group
ステージのみであり、「最大」値のアレイ要素データを見つけるためのプロセス全体を繰り返すことはない:
{
"_id" : {
"bssid" : "b8:a3:86:67:03:56",
"ssid" : "Test Network1"
},
"count" : 2
}
{
"_id" : {
"bssid" : "f4:b7:e2:56:e4:20",
"ssid" : "Test Network2"
},
"count" : 1
}
通常、_idは一意の識別子です。どのようにグループ分けできますか? –
@JohnGreenall質問の論理に従えば、すべての配列に "2"しかないappdata.bssidの値をグループ化するように求めています。質問のポイントは、質問とデータに関連する最善のフレーズとして、*「特定のネットワークがすべてのドキュメントから最大値を持つレベルを数える」*です。そして解決に向けたいくつかの注目すべきアプローチもある問題です。 –