2013-11-19 2 views
0

У меня есть документы, которые имеют поле Version, URL и DateAdded (среди прочих, но это релевантные).запрос MongoDB для разрыва связей и удаления дубликатов

Я хотел бы, чтобы найти все документы, где версия «5,5» и DateAdded меньше или равен 1 января 2013 г. Это довольно просто, но я также хочу следующее поведение:

Если два или более документа имеют один и тот же URL-адрес, а только возвращают тот, у которого есть последний DateAdded (при условии, что он меньше или равен 1 января 2013 года). Было бы здорово, если бы все это могло быть выражено в одном запросе (но моя главная проблема - это производительность).

Я делаю этот последний бит фильтрации в моем клиентском коде (за пределами MongoDB), но это заканчивается неэффективным, не говоря уже о неэлегантном.

Я также пробовал использовать функцию MapReduce от Mongo для достижения того же, но это очень медленно, поскольку, похоже, она копирует большую часть моей коллекции в другую коллекцию.

Есть ли эффективное решение?

+1

Посмотрите на 'aggregate' вместо' mapReduce'. – JohnnyHK

ответ

1

Это должно сделать трюк.

Пример данных:

db.foo.insert({ "_id" : ObjectId("528bd5bded29286a62959513"), "Version" : "5.3", "URL" : "foo.bar.com/asdfwoaef", "DateAdded" : ISODate("2012-10-05T00:00:00Z") }) 
db.foo.insert({ "_id" : ObjectId("528bd5e8ed29286a62959514"), "Version" : "5.6", "URL" : "foo.bar.com/asdfwoaef", "DateAdded" : ISODate("2012-12-05T00:00:00Z") }) 
db.foo.insert({ "_id" : ObjectId("528bd621ed29286a62959515"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2012-11-04T00:00:00Z") }) 
db.foo.insert({ "_id" : ObjectId("528bd629ed29286a62959516"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2012-11-05T00:00:00Z") }) 
db.foo.insert({ "_id" : ObjectId("528bd642ed29286a62959517"), "Version" : "5.5", "URL" : "foo.bar.com/aafoobbb", "DateAdded" : ISODate("2013-01-02T00:00:00Z") }) 
db.foo.insert({ "_id" : ObjectId("528bd744ed29286a62959518"), "Version" : "5.5", "URL" : "foo.bar.com/ccbarcc", "DateAdded" : ISODate("2013-01-02T00:00:00Z") }) 
db.foo.insert({ "_id" : ObjectId("528bd780ed29286a62959519"), "Version" : "5.5", "URL" : "foo.bar.com/ccbarcc", "DateAdded" : ISODate("2012-04-05T00:00:00Z") }) 

Pipeline:

pipeline = [ 
    { 
     "$match" : { 
      "Version" : "5.5", 
      "DateAdded" : { 
       "$lt" : ISODate("2013-01-01T00:00:00Z") 
      } 
     } 
    }, 
    { 
     "$sort" : { 
      "URL" : 1, 
      "DateAdded" : -1 
     } 
    }, 
    { 
     "$group" : { 
      "_id" : "$URL", 
      "doc" : { 
       "$first" : { 
        "id" : "$_id", 
        "DateAdded" : "$DateAdded" 
       } 
      } 
     } 
    } 
] 

db.foo.aggregate(pipeline) 

И вот результат:

{ 
    "result" : [ 
     { 
      "_id" : "foo.bar.com/ccbarcc", 
      "doc" : { 
       "id" : ObjectId("528bd780ed29286a62959519"), 
       "DateAdded" : ISODate("2012-04-05T00:00:00Z") 
      } 
     }, 
     { 
      "_id" : "foo.bar.com/aafoobbb", 
      "doc" : { 
       "id" : ObjectId("528bd629ed29286a62959516"), 
       "DateAdded" : ISODate("2012-11-05T00:00:00Z") 
      } 
     } 
    ], 
    "ok" : 1 
} 
+0

Выглядит многообещающе. Он возвращает: {"result": [], "ok": 1} –

+0

Да, я сделал ..... –

+0

Я разместил обновление с примерами данных. Вы можете проверить это? Я предполагаю, что по какой-то причине вы пропустили все данные в фазе '$ match'. – zero323

Смежные вопросы