Aggregate和$ ne不按预期工作

时间:2018-05-16 16:02:49

标签: mongodb null

我正在尝试下面的聚合,但似乎没有使用 $ 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"
            }
        }
    }}])

2 个答案:

答案 0 :(得分:0)

认为我刚遇到了与您同样的问题。目前正在使用Mongo 3.4。据我所知,在将其与$ne进行比较时,查询 $ne的行为与聚合 null有所不同。把我甩了一下。

具体来说,当{ $ne: [ '$field', null ] }true时,aggregate管道中的$field谓词将返回undefined

但是,当使用queries(而不是$aggregate)时,当{ field: { $ne: null }为{{1}时,对于相同的文档,false谓词将返回$field }。

我的解决方法是在先前的步骤中将undefined$project一起使用,以将该字段的{ field: { $ifNull: [ '$field': null ] } }实例转换为显式undefined,这将使合计null根据需要工作。无论出于何种原因,$ifNull都可用于空,未定义和缺失的字段。不确定$ne为何不同。


这是一个复制的例子。

$ne

答案 1 :(得分:0)

问题是缺少字段是 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"
    }
}