2017-02-17 3 views
4

Я наткнулся на какое-то очень странное поведение с MongoDB. Для моего тестового примера у меня есть коллекция MongoDB с 9 документами. Все документы имеют ту же структуру, в том числе поля expired_at: Date и location: [lng, lat].

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

var qExpiry = {"expired_at": { $gt : new Date() } }; 
var qLocation = { "location" : { $geoWithin : { $box : [ [ 123.8766, 8.3269 ] , [ 122.8122, 8.24974 ] ] } } }; 
var qFull = { $and: [ qExpiry, qLocation ] }; 

Поскольку срок годности давно в прошлом, и когда я поставил рамку достаточно большой, следующие запросы дают мне все 9 документов, как и ожидалось:

db.docs.find(qExpiry); 
db.docs.find(qLocation); 
db.docs.find(qFull); 
db.docs.find(qExpiry).sort({"created_at" : -1}); 
db.docs.find(qLocation).sort({"created_at" : -1}); 

Теперь вот сделка: следующий запрос возвращает 0 документы:

db.docs.find(qFull).sort({"created_at" : -1}); 

Просто добавив вид на запрос и губит результат (обратите внимание, что я хочу, чтобы отсортировать, так как у меня есть литий чтобы избежать загромождения карты в более крупных масштабах). Сортировка по другим полям дает такой же пустой результат. Что тут происходит?

(На самом деле, даже пришельца... Когда я просигналить в мою карту, я иногда получить результаты для qFull, даже с сортировкой Можно утверждать, что qLocation неисправна Но когда я использую только qLocation, результаты всегда правильно и qExpiry всегда верно для всех документов)

+2

Пробовал ли вы использовать тот же запрос, используя конвейеры '$ match' и '$ sort' структуры агрегации? – chridam

+0

@chridam - ничего себе, это сделал трюк! Я дам ответ, так как это может показаться чем-то другим. Любая идея, почему этот способ работал, и мой первоначальный подход нет? – Christian

ответ

2

Вы можете попробовать запустить тот же запрос с использованием структуры агрегации в $match и $sort трубопроводов:

db.docs.aggregate([ 
    { "$match": qFull }, 
    { "$sort": { "created_at": -1 } } 
]); 

или неявно с помощью $and путем specifiying разделенных запятыми список выражений, как в

db.docs.aggregate([ 
    { 
     "$match": { 
      "expired_at": { "$gt" : new Date() }, 
      "location" : { 
       "$geoWithin" : { 
        "$box" : [ 
         [ 123.8766, 8.3269 ], 
         [ 122.8122, 8.24974 ] 
        ] 
       } 
      } 
     } 
    }, 
    { "$sort": { "created_at": -1 } } 
]); 

Не совсем уверен, почему сбой с find()

1

Предложение chridam с использованием структуры агрегации MongoDB оказалось для вас способом. Мой рабочий запрос теперь выглядит следующим образом:

db.docs.aggregate(
    [ 
     { $match : { $and : [qExpiry, qLocation]} }, 
     { $sort: {"created_at": -1} }. 
     { $limit: 50 }. 
    ] 
); 

Тем не менее, если можно указать путь мой первый подход не работал, это было бы очень полезно. Просто добавив sort() к непустому запросу, он не должен внезапно возвращать 0 документов. Просто добавьте, так как я все еще пытался немного, .sort({}) вернуть все документы, но не очень полезен. Все остальное не удалось, включая .sort({'_id': 1}).

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