Вопрос следующий:
Получить документы с тегами в списке, упорядоченные по общему количеству совпадений
Но говорят, что можно с помощью Aggregation Framework, это возможно?
Вопрос следующий:
Получить документы с тегами в списке, упорядоченные по общему количеству совпадений
Но говорят, что можно с помощью Aggregation Framework, это возможно?
Да, это возможно с помощью Aggregation Framework.
Предположения
tags
представляет собой набор (без повторяющихся элементов)Запрос
Этот подход вынуждает вас раскручивать результаты и переоценивать предикат совпадения с раскрученными результатами, поэтому он действительно неэффективен.
db.test_col.aggregate(
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$unwind: "$tags"},
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$group: {
_id:{"_id":1},
matches:{$sum:1}
}},
{$sort:{matches:-1}}
);
Ожидаемые результаты
{
"result" : [
{
"_id" : {
"_id" : ObjectId("5051f1786a64bd2c54918b26")
},
"matches" : 3
},
{
"_id" : {
"_id" : ObjectId("5051f1726a64bd2c54918b24")
},
"matches" : 2
},
{
"_id" : {
"_id" : ObjectId("5051f1756a64bd2c54918b25")
},
"matches" : 1
}
],
"ok" : 1
}
Использование $size и $setIntersection эффективно решит эту проблему, не вызывая умножения памяти.
tagList = ['shirt', 'cotton', 'black']
db.test_col.aggregate(
{$match: {tags: {$in: ["shirt","cotton","black"]}}},
{$project:
{"title":1,"tags":1},
{$order:
{"$size":
{"$setIntersection": [ tagList, "$tags" ]}},
{$sort:{order:-1}}
);
Сначала мы сопоставляем документы, у которых есть хотя бы одно совпадение элементов.
Затем мы проецируем нужные нам ключи/столбцы вместе с новым ключом/столбцом порядка. Порядок создается путем подсчета пересекающихся элементов между «тегами в базе данных» и «тегами из запроса».
Затем делаем простую сортировку по убыванию. Это сработало для меня. Ответ на аналогичный вопрос здесь