3

Запрос получает пару координат, максимальный радиус расстояния, целое число «skip» и целое число «limit». Функция должна возвращать самые близкие и новейшие местоположения в соответствии с заданной позицией. В моем коде нет видимой ошибки, однако, когда я снова вызываю запрос, он возвращает повторяющиеся результаты. Переменная «skip» обновляется в соответствии с возвращенными результатами.Запрос Mongoose, возвращающий повторяющиеся результаты

Пример:

1) Я сделать запрос с пропуском = 0, пределом = 10. Я получаю 10 неповторяющееся местоположения.

2) Запрос снова вызван, skip = 10, limit = 10. Я получаю еще 10 местоположений с повторными результатами первого запроса.

QUERY

Locations.find({ coordinates : 
       { $near : [ x , y ], 
        $maxDistance: maxDistance } 
      }) 
.sort('date_created') 
.skip(skip) 
.limit(limit) 
.exec(function(err, locations) { 
    console.log("[+]Found Locations"); 
    callback(locations); 
}); 

SCHEMA

var locationSchema = new Schema({ 
     date_created: { type: Date }, 
     coordinates: [], 
     text: { type: String } 
}); 

Я пытался повсюду искал решения. Мой единственный вариант - это версии Монго? Я использую mongoose 4.x.x, а mongodb - как 2.5.6. Я верю. Есть идеи?

+1

Ваша сортировка результатов по 'date_created' после выполнения' $ near', что не является отличной идеей и, скорее всего, не тем, что вы хотите, так как оно «отбрасывает» возвращенный «заказ» в результате почти операции. Также следует избегать подхода «пропустить» и «лимит» к поисковому вызову, когда это возможно, и использовать только там, где вам «нужно» пронумеровать пейджинг, чтобы «прыгать», и нет альтернативного пути. Я полагаю, что это намерение - это, по крайней мере, найти «ближайшие» вещи, а «затем» сортировать что-нибудь примерно на таком же расстоянии по порядку творения? –

+0

да точно! Что я могу сделать? – Avi

+0

Как насчет пейджинга? Вам действительно нужны номера страниц, или вы просто можете просто запросить следующую страницу и следующую страницу и так далее. –

ответ

2

Есть несколько вещей, которые следует учитывать здесь в виде результатов, которые вы хотите, с первым соображением, что у вас есть «вторичные» критерии сортировки в «date_created», с которыми нужно иметь дело.

Основная проблема заключается в том, что оператор $near и аналогичные операторы в MongoDB в настоящее время не «проецируют» любое поле, чтобы указать «расстояние» от запрашиваемого местоположения, а просто просто «сортировать по умолчанию» данные. Поэтому для того, чтобы сделать этот «второстепенный» вид, необходимо иметь поле с «расстоянием». Поэтому есть и другие варианты.

Второй случай заключается в том, что подкачка стиля «пропустить» и «ограничение» - это ужасная производительность формы на больших наборах данных, и ее следует избегать там, где вы можете. Поэтому лучше выбирать данные на основе «диапазона», где это происходит, а не «пропускать» все результаты, которые вы ранее отображали.

Первое, что нужно сделать, это использовать команду, которая может «проецировать» расстояние в документ вместе с другой информацией. Команда агрегация $geoNear хороша для этого, и тем более, что мы хотим делать другую сортировку:

var seenIds = [], 
    lastDistance = null, 
    lastDate = null; 

Locations.aggregate(
    [ 
     { "$geoNear": { 
      "near": [x,y], 
      "maxDistance": maxDistance 
      "distanceField": "dist", 
      "limit": 10 
     }}, 
     { "$sort": { "dist": 1, "date_created": -1 } 
    ], 
    function(err,results) { 
     results.forEach(function(result) { 

      if ((result.dist != lastDistance) || (result.date_created != lastDate)) { 
       seenIds = []; 
       lastDistance = result.dist; 
       lastDate = result.date_created; 
      } 
      seenIds.push(result._id); 
     }); 
     // save those variables to session or other persistence 
     // do something with results 
    } 
) 

Это первая итерация ваших результатов, где вы запрашиваете первый 10. отмечая логику внутри цикла, где каждый документ в результатах проверяется либо на изменение «date_created», либо на проецируемое «dist» поле, которое теперь присутствует в документе, и где это происходит, массив «seenIds» уничтожается из всех текущих записей. Общее действие состоит в том, что все переменные тестируются и, возможно, обновляются на каждой итерации и там, где нет изменений, тогда элементы добавляются в список «seenIds».

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

Locations.aggregate(
    [ 
     { "$geoNear": { 
      "near": [x,y], 
      "maxDistance": maxDistance, 
      "minDistance": lastDistance, 
      "distanceField": "dist", 
      "limit": 10, 
      "query": { 
       "_id": { "$nin": seenIds }, 
       "date_created": { "$lt": lastDate } 
      } 
     }}, 
     { "$sort": { "dist": 1, "date_created": -1 } 
    ], 
    function(err,results) { 
     results.forEach(function(result) { 
      if ((result.dist != lastDistance) || (result.date_created != lastDate)) { 
       seenIds = []; 
       lastDistance = result.dist; 
       lastDate = result.date_created; 
      } 
      seenIds.push(result._id); 
     }); 
     // save those variables to session or other persistence 
     // do something with results 
    } 
) 

Так что параметр «minDistance» вводится как вы хотите, чтобы исключить любой из «более близких» результатов, которые уже были замечены, и дополнительные проверки помещаются в запрос с «date_created», который должен быть «меньше» «lastDistance», записанным также, так как мы находимся в порядке убывания сортировки, с окончательным «уверенным» фильтром, исключая любые значения «_id», которые были записаны в списке, потому что значения не изменились.

Теперь с данными геопространственных данных, что список "seenIds" вряд ли будет расти, как обычно, вы не собираетесь находить вещи на одинаковом расстоянии, но это общий процесс подкачки отсортированного списка данных, подобного этому, поэтому это стоит понять концепцию.

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

Общая концепция - «продвигать минимальное расстояние», чтобы каждая страница результатов постепенно «удалялась» от исходной точки происхождения, используемой в запросе.

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