2013-08-07 4 views
5

В моей коллекции каждый документ имеет 2 даты, изменен и синхронизирован. Я хотел бы найти те, которые модифицировали> sync, или sync не существует.Сравните две поля даты в MongoDB

Я попытался

{'modified': { $gt : 'sync' }} 

но это не показывает, что я ожидал. Есть идеи?

Благодаря

ответ

17

Вы не можете сравнить поле со значением другого поля с обычным соответствием запросам. Тем не менее, вы можете сделать это с рамками агрегации:

db.so.aggregate([ 
    { $match: …your normal other query… }, 
    { $match: { $eq: [ '$modified', '$sync' ] } } 
]); 

Я положил ... ваш нормальный другой запрос ... там, как вы можете сделать это немного использовать индекс. Так что если вы хотите сделать это только для документов, где name поле charles вы можете сделать:

db.so.ensureIndex({ name: 1 }); 
db.so.aggregate([ 
    { $match: { name: 'charles' } }, 
    { $project: { 
     modified: 1, 
     sync: 1, 
     name: 1, 
     eq: { $cond: [ { $gt: [ '$modified', '$sync' ] }, 1, 0 ] } 
    } }, 
    { $match: { eq: 1 } } 
]); 

с входом:

{ "_id" : ObjectId("520276459bf0f0f3a6e4589c"), "modified" : 73845345, "sync" : 73234 } 
{ "_id" : ObjectId("5202764f9bf0f0f3a6e4589d"), "modified" : 4, "sync" : 4 } 
{ "_id" : ObjectId("5202765b9bf0f0f3a6e4589e"), "modified" : 4, "sync" : 4, "name" : "charles" } 
{ "_id" : ObjectId("5202765e9bf0f0f3a6e4589f"), "modified" : 4, "sync" : 45, "name" : "charles" } 
{ "_id" : ObjectId("520276949bf0f0f3a6e458a1"), "modified" : 46, "sync" : 45, "name" : "charles" } 

Это возвращает:

{ 
    "result" : [ 
     { 
      "_id" : ObjectId("520276949bf0f0f3a6e458a1"), 
      "modified" : 46, 
      "sync" : 45, 
      "name" : "charles", 
      "eq" : 1 
     } 
    ], 
    "ok" : 1 
} 

Если вы хотите больше полей, вам нужно добавить их в $project.

+0

Спасибо, ребята, как aggr, так и запрос должны работать. –

+1

Вы должны действительно избегать варианта '' $ where'', хотя, поскольку он проходит через Javascript. Также, пожалуйста, примите ответ. – Derick

-1

Сейчас ваш запрос пытается вернуть все результаты, такие, что modified поле больше, чем слово 'sync'. Попытайтесь избавиться от котировок около sync и посмотрите, не исправляет ли это что-либо. В противном случае я сделал небольшое исследование и нашел this question. То, что вы пытаетесь сделать, может оказаться невозможным в одном запросе, но вы сможете управлять своими данными, как только вы вытащите все из базы данных.

+0

Спасибо @ gr3co, я пытался избежать агрегации, но, похоже, единственный путь вперед ... :( –

-1

Чтобы устранить эту проблему без агрегирования изменить запрос к этому: {'modified': { $gt : ISODate(this.sync) }}

1

Просто

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"}) 
> 
0

Использование Javascript, используйте Еогеасп и конвертировать Дата Для toDateString()

db.ledgers.find({}).forEach(function(item){ 

    if(item.fromdate.toDateString() == item.todate.toDateString()) 
    { 
     printjson(item) 
    } 
}) 
Смежные вопросы