我正在尝试下面的聚合,但似乎没有使用$ne和null获得预期的结果。
我尝试过其他解决方案,例如结合使用$cond、$not和$eq,但无济于事。 使用$gt:[ "$unloadeddate",null]似乎给出了一些结果,但这似乎不是正确的语法,我担心在整个数据集上正确运行是不可信的。
此外,查询如下:
db.getCollection('esInvoices').find({"esBlendTickets.loadeddate":{$ne:null}})
。返回结果,因此不确定聚合函数中的相同查询不起作用的原因。
任何帮助不胜感激!!
第一部分工作...
"unloadeddate": { "$switch": {
branches:[ {
case: {
"$ne":[ "$esBlendTickets.ticketdate", null]
},
then: "$esBlendTickets.ticketdate"
}, {
case: {
"$ne":[ "$esDeliveryTickets.ticketdate", null]
},
then: "$esDeliveryTickets.ticketdate"
}],
default: null
}
},
"loadeddate": { "$switch": {
branches:[ {
case: {
"$ne":[ "$esBlendTickets.loadeddate", null]
},
then: "$esBlendTickets.loadeddate"
}, {
case: {
"$ne":[ "$esDeliveryTickets.loadeddate", null]
},
then: "$esDeliveryTickets.loadeddate"
}],
default: null
}
},
。但是这第二部分(除了结果值之外,基本上相同的逻辑)并没有按预期工作......
"stagename": { "$switch": {
branches:[ {
case: {
"$ne":[ "$esDeliveryTickets.ticketdate", null]
},
then: "Invoiced"
}, {
case: {
"$ne":[ "$esBlendTickets.ticketdate", null]
},
then: "Invoiced"
}],
default: "Invoiced-Only"
}
}
完整聚合:
db.esInvoices.aggregate([ {
$addFields: {
// A single invoice will not have both a blend ticket and delivery ticket associated so looping tough each case should work.
"unloadeddate": { "$switch": {
branches:[ {
case: {
"$ne":[ "$esBlendTickets.ticketdate", null]
},
then: "$esBlendTickets.ticketdate"
}, {
case: {
"$ne":[ "$esDeliveryTickets.ticketdate", null]
},
then: "$esDeliveryTickets.ticketdate"
}],
default: null
}
},
"loadeddate": { "$switch": {
branches:[ {
case: {
"$ne":[ "$esBlendTickets.loadeddate", null]
},
then: "$esBlendTickets.loadeddate"
}, {
case: {
"$ne":[ "$esDeliveryTickets.loadeddate", null]
},
then: "$esDeliveryTickets.loadeddate"
}],
default: null
}
},
"stagedate": "$InvoiceHeader.InvDate",
"stagename": { "$switch": {
branches:[ {
case: {
"$ne":[ "$esDeliveryTickets.ticketdate", null]
},
then: "Invoiced"
}, {
case: {
"$ne":[ "$esBlendTickets.ticketdate", null]
},
then: "Invoiced"
}],
default: "Invoiced-Only"
}
}
}}])
想想我刚刚遇到了你遇到的同样的问题。目前使用 Mongo 3.4。据我所知,当您将其与null
进行比较时,查询$ne
的行为与聚合$ne
不同。把我扔了一会儿。
具体而言,聚合管道中的{ $ne: [ '$field', null ] }
谓词将在$field
undefined
时返回true
。
但是,当使用查询(不是$aggregate
)时,当undefined
$field
时,{ field: { $ne: null }
谓词将返回这些相同文档的false
。
我的解决方法是在上一步中使用带有{ field: { $ifNull: [ '$field': null ] } }
的$project
将该字段的实例转换为显式null
undefined
,然后使聚合$ne
根据需要工作。无论出于何种原因,$ifNull都适用于空字段、未定义字段和缺失字段。不知道为什么$ne
不同。
下面是一个要重现的示例。
db.test.insertMany([
{ a: 1, b: 'string' },
{ a: 2, b: null },
{ a: 3 },
])
db.test.find({ b: { $ne: null }}, { _id: 0 })
/*
returns:
{
"a" : 1.0,
"b" : "string"
}
*/
db.test.aggregate([
{ $project: {
_id: 0,
a: 1,
b: 1,
switched: { $switch: {
branches: [
{ case: { $ne: [ '$b', null ] }, then: 'cased' },
],
default: 'default',
}}
}}
])
/*
returns:
{
"a" : 1.0,
"b" : "string",
"switched" : "cased"
},
{
"a" : 2.0,
"b" : null,
"switched" : "default"
},
{
"a" : 3.0,
"switched" : "cased" <--
}
*/
问题是缺少字段undefined
而null
字段是空值。当你写"$ne":[ "$esDeliveryTickets.ticketdate", null]
时,你不会过滤前者,而只会过滤后者。
但undefined
比null
"小".为了过滤它们,您只需要制作lte
/gt
而不是eq
/ne
.因此,此查询返回所有现有值:
请参阅示例:
db.test.insertOne(
{
"a" : 10,
"b" : null
})
...
db.getCollection('mytest').find( {},
{
"a" : { $lte : ["$a", null] },
"b" : { $lte : ["$b", null] },
"c" : { $lte : ["$c", null] },
})
// {
// "_id" : ObjectId("606724f38ec4d26b981b5a1c"),
// "a" : false,
// "b" : true,
// "c" : true
// }
在您的情况下:
"stagename": { "$switch": {
branches:[ {
case: {
"$gt":[ "$esDeliveryTickets.ticketdate", null]
},
then: "Invoiced"
}, {
case: {
"$gt":[ "$esBlendTickets.ticketdate", null]
},
then: "Invoiced"
}],
default: "Invoiced-Only"
}
}
而这个只返回缺失(或空)值:
"stagename": { "$switch": {
branches:[ {
case: {
"$lte":[ "$esDeliveryTickets.ticketdate", null]
},
then: "Invoiced"
}, {
case: {
"$lte":[ "$esBlendTickets.ticketdate", null]
},
then: "Invoiced"
}],
default: "Invoiced-Only"
}
}