Хобрук: Ваш путь к мастерству в программировании

пользовательская сортировка для коллекции mongodb в метеоре

У меня есть эта коллекция продуктов, и я хочу отобразить top 10 products на основе пользовательской функции сортировки.

[{ _id: 1, title, tags:['a'], createdAt:ISODate("2016-01-28T00:00:00Z") } ,
{ _id: 2, title, tags:['d','a','e'], createdAt:ISODate("2016-01-24T00:00:00Z") }]

Что я хочу сделать, так это отсортировать его на основе «магической оценки», которую можно рассчитать. Например, исходя из этой формулы: tag_count*5 - number_of_days_since_it_was_created.

Если первому 1 день, это составляет оценку:

[{_id:1 , score: 4}, {_id:2, score: 10}]

У меня есть несколько идей о том, как я могу этого добиться, но я не уверен, насколько они хороши, тем более что я новичок как в монго, так и в метеоре:

  1. запустите наблюдатель (Meteor.observe) и каждый раз, когда документ изменяется (или создается новый), пересчитывайте оценку и обновляйте ее в самой коллекции. Если я сделаю это, я мог бы просто использовать $orderBy там, где мне это нужно.

  2. после некоторого чтения я обнаружил, что агрегат монго или map_reduce могут помочь мне достичь того же результата, но, насколько я понял, метеор не поддерживает его напрямую

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

Спасибо за любую информацию, которой вы можете поделиться со мной!

01.02.2016

  • Единственный способ сделать это во время выполнения — реализовать агрегатный оператор, поскольку вы не можете предоставить функцию для сортировки на стороне сервера каким-либо другим способом (обратите внимание, что mapReduce не сортирует результаты, за исключением ключей для сокращения, которые сортируются, но также и не подходит для листания по вычисляемому полю). Альтернативный подход, учитывая ваше требование, состоит в том, чтобы хранить поле и просто пересчитывать его ежедневно (и, вероятно, также при обновлении). Это простая запланированная задача, а затем базовая сортировка уже существующего поля. Так же более производительно. 02.02.2016
  • Итак, вместо того, чтобы добавлять прослушиватель событий для каждого обновления продукта, я должен просто время от времени запускать cron? Честно говоря, это имеет смысл, тем более, что мне не нужно, чтобы счет был в реальном времени. Что касается того, как это сделать, должен ли я использовать cursor.each() или есть лучшая альтернатива? Я не понял, могу ли я сделать что-то подобное в mongodb: "UPDATE products SET score = tags_count * 10", где я устанавливаю поле на основе значения других. Спасибо @BlakesSeven 02.02.2016
  • Это была идея. В вашем требовании указаны дни, так что это не похоже на то, что ему нужно реальное время. Хранение предварительно рассчитанных значений кажется определенно подходящим способом. 02.02.2016
  • или вы можете написать пользовательскую функцию публикации, где вы можете делать практически все, что захотите. Вы можете следовать примеру подсчета по комнатам из документации docs.meteor.com/#/full. /meteor_publish. 02.02.2016
  • Я тоже пробовал этот подход, но вы не можете делать все, что хотите. Например, я не смог найти способ использовать этот метод с $limit (поэтому я не публикую все документы). Все, чего я смог добиться, это опубликовать оценку на клиенте вместе со всеми документами `add: function(id, fields) { fields.score = fields.tags.length* 15; self.added (продукты, идентификатор, поля); }` 02.02.2016
  • Возможно, пакет maximum:computed-fields позволит вам вычислить оценку реактивно на стороне сервера. Затем вы можете использовать классический {sort:{score:1}} 06.02.2016

Ответы:


1

Буквальная сортировка функций в настоящее время реализуется в метеоре, поэтому вы сможете сделать что-то вроде

Products.find({}, {sort: scoreComparator});

в следующем выпуске.

Вы можете использовать свойство transform при создании коллекции. В этом преобразовании сохраните волшебную операцию как функцию.

score=function(){
    // return some score
};
transformer=function(product){
  product.score=score; 
  // one could also use prototypal inheritance 
};
Products=new Meteor.Collection('products',{transform:transformer});

К сожалению, вы пока не можете использовать оператор сортировки для виртуальных полей, потому что minimongo его не поддерживает.

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

// Later, within some template 
scoreComparator=function(prd1,prd2){
  return prd1.score()-prd2.score(); 
}
Template.myTemplate.helpers({
  products:function(){
    return Products.find().fetch().sort(scoreComparator);
  }
});

я не уверен, как он будет вести себя с нумерацией страниц (учитывая, что я подписан на ограниченное количество документов)

РЕДАКТИРОВАТЬ : действительно, оценка будет вычисляться среди подписанных документов.

06.02.2016
Новые материалы

Блоги, которые обязательно нужно прочитать специалистам по обработке и анализу данных :
Добро пожаловать в 2020! Новый год и новое десятилетие. Поскольку мы начинаем новый и захватывающий год в науке о данных, важно, чтобы профессионалы открыли для себя лучшие блоги по науке о..

Универсальный базовый доход
Универсальный базовый доход В последние годы концепция всеобщего базового дохода (УБД) набирает обороты как все более эффективное решение для борьбы с растущим неравенством доходов и..

Освоение Python для анализа финансовых данных: руководство по получению данных о доходах от акций
Если вы хотите научиться получать данные о доходах от акций с помощью Python, то это руководство для вас! В этой статье мы рассмотрим несколько примеров сбора данных о доходах от акций. Мы..

Абсолютно имеет смысл.
Абсолютно имеет смысл. Мой репетитор даже предложил то же самое. Одна проблема, с которой я столкнулся, заключается в том, что для каждой из категорий не было ярлыка «хорошо». Если я перебираю..

МАШИННОЕ ОБУЧЕНИЕ И EDA
Каковы шаги в машинном обучении Определение проблемы Генерация гипотез Извлечение данных Исследование данных Прогнозное моделирование Развертывание модели Зачем нам ЭДА? Идентификация..

В чем основные различия между ReactJS и React-Native?
В чем основные различия между ReactJS и React-Native? Что я узнал, создавая веб-приложения, а затем мобильные приложения на React React-Native существует уже около 2 лет и стал..

LeetCode — Умножение строк
Постановка задачи Даны два неотрицательных целых числа num1 и num2 , представленные в виде строк, вернуть произведение num1 и num2 , а также представлен в виде строки. Примечание . Вы..