Сравнение двух полей даты в 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) }}