[英]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")]
}
])
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.