Как рассчитать рейтинг в моем дизайне MongoDB
Я создаю систему, в которой пользователи могут написать отзыв о товаре и оценить его от 0 до 5. Я использую MongoDB для этого. И моя проблема заключается в том, чтобы найти лучшее решение для расчета общего рейтинга в схеме продукта. Я не думаю, что запрос всех комментариев, чтобы получить размер и деление его на общий рейтинг, является хорошим решением. Вот моя схема. Я ценю любой совет:
Комментарии:
var commentSchema = new Schema({
Rating : { type: Number, default:0 },
Helpful : { type: Number, default:0 },
User :{
type: Schema.ObjectId,
ref: 'users'
},
Content: String,
});
Вот моя схема Item:
var productSchema = new Schema({
//id is barcode
_id : String,
Rating : { type: Number, default:0 },
Comments :[
{
type: Schema.ObjectId,
ref: 'comments'
}
],
});
РЕДАКТИРОВАТЬ: ЗДЕСЬ это решение, которое я получил из другой темы: вычисление среднего в Mongoose
2 ответа
Вы можете получить общее количество, используя структуру агрегации. Сначала вы используете оператор $ unwind, чтобы превратить комментарии в поток документов:
{ $unwind: "$Comments" }
В результате каждый продукт-документ превращается в один документ-продукт для каждой записи в его Comments
массив. Эта запись комментария превращается в один объект под полем Comments
все остальные поля взяты из исходного продукта-документа.
Затем вы используете $ group, чтобы присоединиться к документам для каждого продукта по их _id, а оператор $ avg вычисляет среднее значение поля рейтинга:
{ $group: {
_id: "$_id",
average: { $avg: "$Comments.Rating" }
} }
Помещение этих двух шагов в конвейер агрегации позволяет рассчитать среднюю оценку для каждого продукта в вашей коллекции. Вы можете захотеть сузить его до одного или небольшого подмножества продуктов, в зависимости от того, что пользователь запросил прямо сейчас. Для этого перед конвейером добавьте шаг $ match. Объект $ match работает так же, как тот, который вы передаете find()
,
Основной вопрос, который было бы полезно понять, заключается в том, почему вы не думаете, что поиск всех рейтингов, их суммирование и деление на общее число - это полезный подход. Понимание основной причины поможет найти лучшее решение.
Исходя из комментариев, приведенных ниже, кажется, что вашей главной заботой является производительность и необходимость запуска карты-уменьшения (или другой структуры агрегации) каждый раз, когда пользователь хочет увидеть итоговые оценки.
Этот человек обратился к аналогичной проблеме здесь: http://markembling.info/2010/11/using-map-reduce-in-a-mongodb-app
Решение, которое они определили, состояло в том, чтобы отделить выполнение функции карты-уменьшения от потребности в представлении, чтобы увидеть общее значение. В этом случае оптимальным решением было бы периодически запускать карту-уменьшение и сохранять результаты в другой коллекции, а также иметь среднюю оценку на основе коллекции, в которой хранятся средние значения, вместо того, чтобы каждый раз выполнять вычисления в реальном времени.
Как я уже упоминал в предыдущей версии этого ответа, вы можете еще больше повысить производительность, ограничив сокращение карты до добавления рейтингов, которые были созданы или обновлены совсем недавно, или с момента последней агрегации уменьшения карты.