聚合和$ne无法按预期工作

  • 本文关键字:工作 ne mongodb null
  • 更新时间 :
  • 英文 :


我正在尝试下面的聚合,但似乎没有使用$nenull获得预期的结果。

我尝试过其他解决方案,例如结合使用$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 ] }谓词将在$fieldundefined时返回true

但是,当使用查询(不是$aggregate)时,当undefined$field时,{ field: { $ne: null }谓词将返回这些相同文档的false

我的解决方法是在上一步中使用带有{ field: { $ifNull: [ '$field': null ] } }$project将该字段的实例转换为显式nullundefined,然后使聚合$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" <--
}
*/

问题是缺少字段undefinednull字段是空值。当你写"$ne":[ "$esDeliveryTickets.ticketdate", null]时,你不会过滤前者,而只会过滤后者。

undefinednull"小".为了过滤它们,您只需要制作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"
}
}

相关内容

  • 没有找到相关文章

最新更新