Сравнение двух полей даты в MongoDB
в моей коллекции каждый документ имеет 2 даты, измененный и синхронизации. Я хотел бы найти те, которые изменены > синхронизация, или синхронизация не существует.
пробовал
{'modified': { $gt : 'sync' }}
но это не показывает, что я ожидал. Есть идеи?
спасибо
6 ответов
вы не можете сравнить поле со значением другого поля с обычным соответствием запроса. Однако вы можете сделать это с помощью aggregation framework:
db.so.aggregate( [
{ $match: …your normal other query… },
{ $match: { $eq: [ '$modified', '$sync' ] } }
] );
Я положил ... ваш обычный другой запрос... там, как вы можете сделать этот бит использовать индекс. Поэтому, если вы хотите сделать это только для документов, где
просто
db.collection.find({$where:"this.modified>this.sync"})
пример
Kobkrits-MacBook-Pro-2:~ kobkrit$ mongo
MongoDB shell version: 3.2.3
connecting to: test
> db.time.insert({d1:new Date(), d2: new Date(new Date().getTime()+10000)})
WriteResult({ "nInserted" : 1 })
> db.time.find()
{ "_id" : ObjectId("577a619493653ac93093883f"), "d1" : ISODate("2016-07-04T13:16:04.167Z"), "d2" : ISODate("2016-07-04T13:16:14.167Z") }
> db.time.find({$where:"this.d1<this.d2"})
{ "_id" : ObjectId("577a619493653ac93093883f"), "d1" : ISODate("2016-07-04T13:16:04.167Z"), "d2" : ISODate("2016-07-04T13:16:14.167Z") }
> db.time.find({$where:"this.d1>this.d2"})
> db.time.find({$where:"this.d1==this.d2"})
>
используйте Javascript, используйте foreach и преобразуйте Date в toDateString ()
db.ledgers.find({}).forEach(function(item){
if(item.fromdate.toDateString() == item.todate.toDateString())
{
printjson(item)
}
})
для MongoDB 3.6 и новее:
на $expr
оператор позволяет использовать выражения агрегации в языке запросов, таким образом, вы можете сделать следующее:
db.test.find({ "$expr": { "$gt": ["$modified", "$sync"] } })
или использование aggregation framework с $match
трубопровод
db.test.aggregate([
{ "$match": { "$expr": { "$gt": ["$modified", "$sync"] } } }
])
Для MongoDB 3.0+:
вы также можете использовать структуру агрегации с $redact
оператор конвейера, который позволяет обрабатывать логическое условие с помощью $cond
оператор и использует специальные операции $$KEEP
"сохранить" документ, где логическое условие true или $$PRUNE
"удалить" документ, где условие было ложным.
рассмотрите возможность выполнения следующей агрегатной операции, которая демонстрирует приведенную выше концепцию:
db.test.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": ["$modified", "$sync"] },
"$$KEEP",
"$$PRUNE"
]
} }
])
эта операция похожа на операцию $project
конвейер, который выбирает поля в коллекции и создает новое поле, содержащее результат запроса логического условия, а затем последующее $match
, только $redact
использует один этап конвейера, который является более эффективным:
сейчас ваш запрос пытается вернуть все результаты, такие, что modified
поле больше, чем слово 'sync'
. Попробуйте избавиться от кавычек вокруг sync
и посмотрим, исправит ли это что-нибудь. В противном случае, я сделал небольшое исследование и нашел этот вопрос. То, что вы пытаетесь сделать, может быть невозможно в одном запросе, но вы должны иметь возможность манипулировать своими данными, как только вытащите все из базы данных.
чтобы устранить эту проблему без агрегации, измените запрос на это:
{'modified': { $gt : ISODate(this.sync) }}