ElasticSearch |Как искать в списке строк, содержащих пробелы? - PullRequest
1 голос
/ 11 июня 2019

Я создаю приложение, в котором пользователи могут вводить свои навыки, а компании могут искать (используя ElasticSearch) пользователей с определенными навыками.

Я создаю такой индекс:

client.indices.create({
    index: "candidates",
    body: {
      mappings: {
        candidate: {
          properties: {
            languages: {type: 'text'},
            skills: {type: 'text'},
          },
        },
      },
    },
  }, (err, data) => {
    if (err) console.log('err ', err);
    if (data) console.log('data ', data);
  })
}

В следующем примере я хочу выполнить поиск пользователей, обладающих навыками «Реклама в Facebook» и «Интернет-маркетинг».

Результаты должны быть отсортированы, поэтому пользователи с двумя совпадениями должны быть наверху.

{
  "index": "candidates",
  "type": "candidate",
  "size": 10000,
  "body": {
    "query": {
      "bool": {
        "must": [
          {
            "bool": {
              "should": {
                "terms": {
                  "skills": [
                    "facebook ads",
                    "online marketing"
                  ]
                }
              }
            }
          }
        ]
      }
    }
  }
}

Этот запрос возвращает ноль результатов.

Проблема : Как объяснено здесь Мне следует избегать использования term (или terms) для text fields.

Вопрос: Как реализовать поисковый запрос, который принимает массив строк (некоторые из которых содержат пробелы) в качестве входных данных и возвращает список упорядоченных совпадений?Под упорядоченными попаданиями я подразумеваю, что пользователи, которые соответствуют большинству навыков в запросе, должны быть наверху.

РЕДАКТИРОВАТЬ

Вот пример пользователя, который имеет навыки как с объявлениями Facebook и Google Ads:

{
        "_index" : "candidates",
        "_type" : "candidate",
        "_id" : "2fbbd818-sdhkfgkjhg-3235465hgfds",
        "_score" : 9.1202545,
        "_source" : {
          "skills" : [
            "Online strategi",
            "Facebook Ads",
            "Google Ads"
          ],
          "languages": [
            "da",
            "en"
          ]
        }
      },

Поиск по [«Объявления Facebook», «Объявления Google»] должны вернуть вышеуказанного пользователя вверху (соответствует как объявлениям Facebook, так и объявлениям Google), но также должны быть возвращены пользователи только с одним соответствием.

Ответы [ 2 ]

2 голосов
/ 11 июня 2019

Хорошо. Вот что я сделал

1) created the mappings for the data
2) indexed 3 documents. One document is same one as you posted above and one 
   is completely irrelevant data, and the third document has one search field 
   matching, so less relevance than the first document but more relevance 
   than the other document
3) the search query

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

Также обратите внимание, чтоЯ передаю несколько строк, как вы ожидали, используя двойные кавычки и одинарные кавычки в поисковом запросе.Вы можете создать массив строк или строку с конкатенированными строками (с пробелами, как вы хотели и т. Д.) .. должно работать

Вот отображение

  PUT ugi-index2
    {
      "mappings": {
        "_doc": {
           "properties":{
             "skills": {"type": "text"},
             "languages": {"type": "keyword"}
        }
       }
     }
    }

и три документа, которые яindexed

   POST /ugi-index2/_doc/3
     {
        "skills" : [
           "no skill",
           "Facebook ads",
           "not related"
          ],
        "languages": [
           "ab",
           "cd"
         ]

    }

  POST /ugi-index2/_doc/2
   {
      "skills" : [
           "no skill",
           "test skill",
           "not related"
           ],
          "languages": [
            "ab",
            "cd"
           ]

    }




   POST /ugi-index2/_doc/1
     {
        "skills" : [
           "Online strategi",
           "Facebook Ads",
           "Google Ads"
         ],
         "languages": [
          "da",
          "en"
         ]

     }

И поисковый запрос

  GET /ugi-index2/_search
    {
      "query":{
      "multi_match": {
       "query": "'Online Strate', 'Facebook'",
       "fields": ["skills"]
     }
    }
   }

посмотрите на приведенный выше запрос для нескольких строк с пробелами (для поиска)

и вот ответ

{
  "took" : 8,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "ugi-index2",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.5753642,
        "_source" : {
          "skills" : [
            "Online strategi",
            "Facebook Ads",
            "Google Ads"
          ],
          "languages" : [
            "da",
            "en"
          ]
        }
      },
      {
        "_index" : "ugi-index2",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.2876821,
        "_source" : {
          "skills" : [
            "no skill",
            "Facebook ads",
            "not related"
          ],
          "languages" : [
            "ab",
            "cd"
          ]
        }
      }
    ]
  }
}
1 голос
/ 11 июня 2019

Если вы хотите соответствовать точному термину, убедитесь, что вы также сохранили навык в качестве ключевого слова.Это оставит пространство нетронутым и позволит точное совпадение.Распространенным способом использования этого в пользовательском интерфейсе является предоставление фильтра с данными ключевого слова в качестве предопределенных параметров фильтра.

Если вы все еще хотите использовать полнотекстовый поиск, когда пользователь может предоставить произвольные данные поиска, вы можете полагаться на тот факт, что документ, содержащий «Facebook» и «Реклама», вернется с более высоким счетом, чем документсодержащий только "Facebook".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...