#mongodb
#mongodb
Вопрос:
Коллекция примеров «test», (с текстовым индексом в field1, field2, field3) :
/* Item 1 */
{
"_id" : ObjectId("6011862888de9cd2347828e6"),
"field1" : "Denver Segment1",
"field2" : "student1 zero1",
"field3" : "cat2 dog0"
}
/* Item 2 */
{
"_id" : ObjectId("6011866b88de9cd234782906"),
"field1" : "meow cap",
"field2" : "teacher eleven1",
"field3" : "cat2 cow"
}
/* Item 3 */
{
"_id" : ObjectId("6011868b88de9cd234782909"),
"field1" : "bark cake",
"field2" : "admin hey",
"field3" : "bird chirp"
}
И я пытаюсь отсортировать записи по количеству совпадающих ключевых слов.
У меня есть следующий запрос (ключевые слова cat2 и student1)
db.getCollection('test').find(
{ $text: { $search: "cat2 student1" } },
{ score: { $meta: "textScore" } }
).sort( { score: { $meta: "textScore" } } )
Результат следующий:
/* 1 */
{
"_id" : ObjectId("6011862888de9cd2347828e6"),
"field1" : "Denver Segment1",
"field2" : "student1 zero1",
"field3" : "cat2 dog0",
"score" : 1.5
}
/* 2 */
{
"_id" : ObjectId("6011866b88de9cd234782906"),
"field1" : "meow cap",
"field2" : "teacher eleven1",
"field3" : "cat2 cow",
"score" : 0.75
}
Это нормально, но я не знаю, как также отобразить фактические ключевые слова.
Например, ожидаемый результат должен быть следующим:
/* 1 */
{
"_id" : ObjectId("6011862888de9cd2347828e6"),
"field1" : "Denver Segment1",
"field2" : "student1 zero1",
"field3" : "cat2 dog0",
"score" : 1.5,
"matched-keywords":["cat2","student1"]
}
/* 2 */
{
"_id" : ObjectId("6011866b88de9cd234782906"),
"field1" : "meow cap",
"field2" : "teacher eleven1",
"field3" : "cat2 cow",
"score" : 0.75,
"matched-keywords":["cat2"]
}
```
How can I do this ?
Ответ №1:
Используя конвейер агрегации, вы можете достичь желаемого результата.
Этапы:
- Текстовый поиск.
- Сортировка по убыванию баллов, используйте выражение $meta aggregation на этапе $sort.
- Разделите его и добавьте новое поле с именем matched-keywords.
- Отфильтруйте совпадающие ключевые слова, используя $regexMatch.
.
db.collection.aggregate([
{
"$match": {
"$text": {
"$search": "cat2 cow"
}
}
},
{
"$sort": {
score: {
"$meta": "textScore"
}
}
},
{
"$addFields": {
"matched-keywords": {
"$concatArrays": [
{
"$split": [
"$field1",
" "
]
},
{
"$split": [
"$field2",
" "
]
},
{
"$split": [
"$field3",
" "
]
}
]
}
}
},
{
"$addFields": {
"matched-keywords": {
"$filter": {
"input": "$matched-keywords",
"as": "word",
"cond": {
"$regexMatch": {
"input": "cat2 cow",
"regex": "$word"
}
}
}
}
}
}
])
Результат:
[
{
"_id": 1,
"field1": "Denver Segment1",
"field2": "student1 zero1",
"field3": "cat2 dog0",
"matched-keywords": [
"cat2"
]
},
{
"_id": 2,
"field1": "meow cap",
"field2": "teacher eleven1",
"field3": "cat2 cow",
"matched-keywords": [
"cat2",
"cow"
]
}
]
Комментарии:
1. Ханиэль, я попробовал ваше решение для одного поля, кажется, оно работает. Но мой текстовый индекс находится во всех трех полях (field1, field2, field3), в этом случае, как я могу это использовать? не могли бы вы меня направить?
2. Привет. Я думаю, что ваш ответ сработал, когда я использовал конкатурации. Не могли бы вы обновить свой комментарий, чтобы я мог пометить его как ответ. Ниже приведен код, который я использовал { «$addFields»: { «matched-keywords»: { «$concatArrays»: [{ «$ split»: [ «$field1″, » » ]}, {«$ разделить»: [ «$field2″, » » ]},{«$split»: [ «$field3″, » » ]} ] } } },
3. Также у меня есть еще один вопрос. Что означает слово $$word ? зачем удваивать «$»?
4. Хороший вопрос. Для доступа к значению переменной «word» префикс имени переменной с двойными знаками доллара ($$); т.е. «$$ <переменная>». Переменные в выражениях агрегирования