Как изменить позицию результата на основе параметра в запросе mongodb / mongoose? - PullRequest
2 голосов
/ 05 января 2012

Поэтому я использую mongoose и node.js для доступа к базе данных mongodb. Я хочу увеличить каждый результат на основе числа (они упорядочены по дате создания, если ни один не увеличен). Например:

{ name: 'A',
  bump: 0 },

{ name: 'B',
  bump: 0 },

{ name: 'C',
  bump: 2 },

{ name: 'D',
  bump: 1 }

будет получено в следующем порядке: C, A, D, B. Как это можно сделать (без перебора каждой записи в базе данных)?

Ответы [ 4 ]

2 голосов
/ 14 января 2012

Попробуйте что-нибудь подобное. Сохраните счетчик, отслеживающий общее количество потоков, назовем его thread_count, изначально установленным в 0, поэтому где-нибудь документ будет выглядеть как {thread_count:0}.

Каждый раз, когда создается новый поток, сначала вызывайте findAndModify(), используя {$inc : {thread_count:1}} в качестве модификатора, т.е. увеличивайте счетчик на 1 и возвращайте его новое значение.

Затем, когда вы вставляете новый поток, используйте новое значение для счетчика в качестве значения для поля в его документе, назовем его post_order.

Таким образом, каждый вставленный вами документ каждый раз имеет значение, равное 1. Например, первые 3 документа, которые вы вставите, будут выглядеть так:

{name:'foo', post_order:1, created_at:... } // value of thread_count is at 1 {name:'bar', post_order:2, created_at:... } // value of thread_count is at 2 {name:'baz', post_order:3, created_at:... } // value of thread_count is at 3 и т.д.

Таким образом, вы можете запрашивать и заказывать по post_order как ASCENDING, и он будет возвращать их в порядке от самого старого к новейшему (или по убыванию от самого нового к старому).

Затем, чтобы «поднять» поток в порядке его сортировки при голосовании, вы можете вызвать update() в документе с помощью {$inc:{post_order:1}}. Это повысит его на 1 в порядке сортировки результатов. Если два потока имеют одинаковое значение для post_order, созданный_ат будет различать, какой из них идет первым. Таким образом, вы будете сортировать по post_order, created_at.

Вам понадобится индекс для post_order и created_at.

1 голос
/ 10 января 2012

Я не думаю, что возможно чисто основанное на запросах решение с вашей схемой документа (я предполагаю, что у вас есть поля createdDate и bump). Вместо этого я предлагаю одно поле с именем sortorder, чтобы отслеживать желаемый порядок поиска:

  1. sortorder изначально является отметкой времени создания. Если нет «выпуклостей», сортировка по этому полю дает правильный порядок.
  2. Если есть «удар», sortorder становится недействительным. Поэтому просто исправьте значения sortorder: каждый раз, когда происходит «удар», меняйте поля sortorder документа с разметкой и документа непосредственно перед ним. Это буквально «поднимает» документ в порядке сортировки.
  3. При запросе сортируйте по sortorder.

Вы можете удалить поля bump и createdDate, если они не используются в других местах.


Кроме того, большинство социальных сайтов напрямую не манипулируют отображаемой позицией поста на основе его количества голосов (или "ударов"). Вместо этого для подсчета очков используется количество голосов. Затем сообщения сортируются и отображаются по этой оценке. В вашем случае вы должны объединить createdDate и bumps в один счет, который может быть отсортирован в запросе.

На этом сайте (StackOverflow.com) было связано мета-обсуждение о том, как определять «горячие» вопросы. Я думаю, что было даже соревнование, чтобы придумать новую формулу. В мета-вопросе также использовались формулы, используемые двумя другими популярными социальными новостными сайтами: Y Combinator Hacker News и Reddit.

1 голос
/ 13 января 2012

Не приятный ответ, но решение, которое вы запрашиваете, нереально.Вот мое предложение:

  1. Добавьте свойство OrderPosition к своему объекту вместо Bump.

  2. Думайте о "неровности" как о событии.Лучше всего представлять как функцию-обработчик событий.Когда элемент «сталкивается» с каким-либо триггером в вашей бизнес-логике, коллекция элементов должна быть скорректирована.

    var currentOrder = this.OrderPosition
    this.OrderPosition = currentOrder - bump;  // moves your object up the list
    // write a foreach loop here, iterating every item AFTER the items unadjusted
    // order, +1 to move them all down the list one notch.    
    

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

1 голос
/ 07 января 2012

Давайте предположим, что ваш код - это переменная response (которая является массивом), тогда я бы сделал:

response.sort(function(obj1, obj2){
  return obj2.bump - obj1.bump;
});

или, если вы хотите также принять во внимание порядок имен:

response.sort(function(obj1, obj2){
  var diff = obj2.bump - obj1.bump;
  var nameDiff = (obj2.name > obj1.name)?-1:((obj2.name < obj1.name)?1:0);
  return (diff == 0) ? nameDiff : diff;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...