私は、この質問がどこかで既に尋ねられて、答えられていないと信じるのに苦労します、しかし、私はそれの少しの痕跡も見つけることができません。
ブール値でグループ化する必要があるMongoDB集計クエリがあります:別のフィールドの存在。
たとえば、このコレクションから始めましょう。
> db.test.find()
{ "_id" : ObjectId("53fbede62827b89e4f86c12e"),
"field" : ObjectId("53fbede62827b89e4f86c12d"), "name" : "Erik" }
{ "_id" : ObjectId("53fbee002827b89e4f86c12f"), "name" : "Erik" }
{ "_id" : ObjectId("53fbee092827b89e4f86c131"),
"field" : ObjectId("53fbee092827b89e4f86c130"), "name" : "John" }
{ "_id" : ObjectId("53fbee122827b89e4f86c132"), "name" : "Ben" }
2つのドキュメントには「フィールド」があり、2つにはありません。 「フィールド」の各値は異なる場合があることに注意してください。その存在に基づいてグループ化したいだけです(または、null以外の場合も機能します。null値は保存されていません)。
$ projectを使用してみましたが、$ existsは存在せず、$ condと$ ifNullは役に立ちませんでした。フィールドは、存在しない場合でも常に存在するように見えます。
> db.test.aggregate(
{$project:{fieldExists:{$cond:[{$eq:["$field", null]}, false, true]}}},
{$group:{_id:"$fieldExists", count:{$sum:1}}}
)
{ "_id" : true, "count" : 4 }
次のはるかに単純な集計が機能することを期待しますが、何らかの理由でこの方法では$ existsはサポートされていません。
> db.test.aggregate({$group:{_id:{$exists:"$field"}, count:{$sum:1}}})
assert: command failed: {
"errmsg" : "exception: invalid operator '$exists'",
"code" : 15999,
"ok" : 0
} : aggregate failed
Error: command failed: {
"errmsg" : "exception: invalid operator '$exists'",
"code" : 15999,
"ok" : 0
} : aggregate failed
at Error (<anonymous>)
at doassert (src/mongo/Shell/assert.js:11:14)
at Function.assert.commandWorked (src/mongo/Shell/assert.js:244:5)
at DBCollection.aggregate (src/mongo/Shell/collection.js:1149:12)
at (Shell):1:9
2014-08-25T19:19:42.344-0700 Error: command failed: {
"errmsg" : "exception: invalid operator '$exists'",
"code" : 15999,
"ok" : 0
} : aggregate failed at src/mongo/Shell/assert.js:13
このようなコレクションから望ましい結果を得る方法を知っている人はいますか?
期待される結果:
{ "_id" : true, "count" : 2 }
{ "_id" : false, "count" : 2 }
私は昨夜、同じ方法でこの問題を解決しました:
> db.test.aggregate({$group:{_id:{$gt:["$field", null]}, count:{$sum:1}}})
{ "_id" : true, "count" : 2 }
{ "_id" : false, "count" : 2 }
http://docs.mongodb.org/manual/reference/bson-types/#bson-types-comparison-order をご覧ください。
未定義をチェックして解決しました
$ne : [$var_to_check, undefined]
または
$ne: [ { $type : "$var_to_check"}, 'missing'] }
Varが定義されている場合、これはtrueを返します
$exists
演算子は「クエリ」演算子であるため、基本的に結果を「フィルタリング」するために使用されます論理条件を識別するよりも。
「論理」演算子として、集計フレームワークは $ifNull
演算子をサポートします。これは、存在するフィールド値、または存在しないか、null
と評価される代替提供値を返します。
db.test.aggregate([
{ "$group": {
"_id": { "$ifNull": [ "$field", false ] },
"count": { "$sum": 1 }
}}
])
しかし、もちろん、それは「true/false」比較ではないので、実際にフィールドが存在するフィールドの実際の値を返さない限り、おそらく $cond
あなたのような文:
db.test.aggregate([
{ "$group": {
"_id": { "$cond": [{ "$eq": [ "$field", null ] }, true, false ] },
"count": { "$sum": 1 }
}}
])
$ifNull
が非常に役立つのは、$unwind
。その後、単一要素または空の配列を返すなどの操作を行うことができるため、残りのパイプライン処理で問題が発生することはありません。
ダンノはどうだったが、今では2019年にクリーンなソリューションがあります。集約パイプラインでこれを行います
$match: {"my_field": {$ne: null}}
素敵なことは私の言語にあります 'ne'はないことを意味します:)
私の答えは:
{'$project': {
'field_exists': {'$or': [
{'$eq': ['$field', null]},
{'$gt': ['$field', null]},
]},
}}
詳細は次のとおりです。 $ existsは、null
またはその他の空の値であっても、フィールドが存在することを意味します。このため、このページのすべての回答が間違っています。
少しテストしてみましょう。これをチェックして:
// Let's take any collection that have docs
db.getCollection('collection').aggregate([
// Get arbitrary doc, no matter which, we won't use it
{"$limit": 1},
// Project our own fields (just create them with $literal)
{'$project': {
'_id': 0,
'null_field': {'$literal': null},
'not_null_field': {'$literal': {}},
}},
])
これを取得します。
{
"null_field" : null,
"not_null_field" : {}
}
次に、このドキュメントに存在するフィールドを明確にしましょう。
さて、上で述べたプロジェクト段階をテストする時が来ました。興味のあるすべてのフィールドに追加しましょう:
{'$project': {
'null_field_exists': {'$or': [
{'$eq': ['$null_field', null]},
{'$gt': ['$null_field', null]},
]},
'not_null_field_exists': {'$or': [
{'$eq': ['$not_null_field', null]},
{'$gt': ['$not_null_field', null]},
]},
'non_existent_field_exists': {'$or': [
{'$eq': ['$non_existent_field', null]},
{'$gt': ['$non_existent_field', null]},
]},
}},
私たちが得るものは:
{
"null_field_exists" : true,
"not_null_field_exists" : true,
"non_existent_field_exists" : false
}
正しい!
ちょっとした注意:null
を比較に使用します。これは、少なくとも価値があるため、最も小さい値です(小さいほど、存在しないだけです)。