Поиск количества совпадающих ключевых слов в текстовом индексе в mongodb

#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:

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

Этапы:

  1. Текстовый поиск.
  2. Сортировка по убыванию баллов, используйте выражение $meta aggregation на этапе $sort.
  3. Разделите его и добавьте новое поле с именем matched-keywords.
  4. Отфильтруйте совпадающие ключевые слова, используя $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» префикс имени переменной с двойными знаками доллара ($$); т.е. «$$ <переменная>». Переменные в выражениях агрегирования