繁体   English   中英

查询所有数组项均大于指定条件的位置

[英]Query where all array items are greater than a specified condition

我有一个包含日期数组的模型。 我使用$gte运算符作为查询集合的条件,其中日期数组中所有元素都是给定日期的$gte

例如,我有此文档:

{ dates: [
    ISODate("2016-10-24T22:00:00.000+0000"), 
    ISODate("2017-01-16T23:00:00.000+0000")]
} 

当我运行此查询{dates: {$gte: new Date()}} ,结果就是整个文档。 但是我想要一个结果,其中每个数组项都与我的查询匹配,而不仅仅是一个查询。

您可以使用$not和比较条件的倒置来实现:

db.test.find({dates: {$not: {$lt: new Date()}}})

因此,这与docs匹配,而不是存在dates元素的值小于当前时间的情况; 换句话说,所有dates值都> =当前时间。

您还可以将聚合框架与$redact管道运算符一起使用,该框架允许您通过$cond运算符处理逻辑条件,并使用特殊操作$$KEEP来“保留”逻辑条件为true或$$PRUNE的文档。在条件为假的情况下“删除”文档。

此操作类似于使用$project管道来选择集合中的字段,并创建一个新字段来保存逻辑条件查询的结果,然后再保存随后的$match ,除了$redact使用单个管道阶段,该阶段更高效。

至于逻辑条件,您可以使用Set Operators ,因为它们允许表达式对数组执行set操作,并将数组视为set。 这两个运算符,即$allElementTrue$map运算符可以用作逻辑条件表达式,因为它们的工作方式是,如果数组中的所有元素实际上都是$gte指定的日期,那么这是真的匹配,文档“保留”。 否则,将其“修剪”并丢弃。


考虑以下示例,这些示例演示了上述概念:

填充测试集

db.test.insert([
    { dates: [
        ISODate("2016-10-24T22:00:00.000+0000"), 
        ISODate("2017-01-16T23:00:00.000+0000")]
    } ,
    { dates: [
        ISODate("2017-01-03T22:00:00.000+0000"), 
        ISODate("2017-01-16T23:00:00.000+0000")]
    } 
])

$redact$setEquals

db.test.aggregate([
    { "$match": { "dates": { "$gte": new Date() } } },
    {
        "$redact": {
            "$cond": [
                { 
                    "$allElementsTrue": {
                        "$map": {
                            "input": "$dates",
                            "as": "date",
                            "in": { "$gte": [ "$$date", new Date() ] }
                        }
                    } 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

样本输出

{
    "_id" : ObjectId("581899dda450d81cb7d87d3a"),
    "dates" : [ 
        ISODate("2017-01-03T22:00:00.000Z"), 
        ISODate("2017-01-16T23:00:00.000Z")
    ]
}

另一种不太优雅的方法是将$where (作为最后的手段)与Array.prototype.every()方法一起使用:

db.test.find({ "$where": function(){ 
    return this.dates.every(function(date) {
        return date >= new Date();
    })}
})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM