Elasticsearch: все префиксы должны появляться в документе - PullRequest
0 голосов
/ 06 апреля 2020

Я использую match_phrase_prefix, но я хочу, чтобы все слова в запросе обрабатывались как префиксы, и эти префиксы должны появляться в документе независимо от порядка. С дополнительными токенами в документе все в порядке.

Например, поиск Nik shoe Mi c Jord должен соответствовать:

  1. Nik e обувь носят Mi c hael Jord an
  2. Mi c hael Джорд носит башмак с Ник е

Однако следующее не должно совпадать:

  1. Майк Джордан (, потому что присутствует только префикс Джорд )
  2. Найк принадлежит Майклу Джордану (, потому что префикс обуви отсутствует )

Итак, вопросы: как я могу рассматривать все слова как префиксы, и как я могу гарантировать, что все префиксы появляются в документе?

Ответы [ 2 ]

1 голос
/ 06 апреля 2020

Хотя решение, данное @jaspreet, будет работать, но оно требует создания краевых n-граммовых токенов и, кроме нахождения правильного баланса min and max ngram, оно может создать огромный размер индекса для небольшой доли запросов и вызывает проблемы с производительностью, и для изменения этого параметра снова и снова потребуется повторная индексация.

Другое решение для этого заключается в использовании запросов с префиксами, специально созданных для таких сценариев использования , как показано в следующем примере, только с одним предупреждением, поскольку вы используете поиск с учетом регистра (в идеале следует использовать строчные буквы для всех условий поиска, чтобы сделать поиск без учета регистра и также наилучшим вариантом).

Простой индекс Def

{
  "mappings": {
    "properties": {
      "title": {
        "type": "text" 
      }
    }
  }
}

Индекс всех 4 примеров документов

{
  "title" : "Nike shoes are worn by Michael Jordan"
}


{
  "title" : "Michael Jordan wears shoes from Nike"
}

{
  "title" : "Mike Jordan"
}

{
  "title" : "Nike is owned by Michael Jordan"
}

Префикс поискового запроса

{
    "query": {
        "bool": {
            "must": [
                {
                    "prefix": {
                        "title": {
                            "value": "nik"
                        }
                    }
                },
                {
                    "prefix": {
                        "title": {
                            "value": "shoe"
                        }
                    }
                },
                {
                    "prefix": {
                        "title": {
                            "value": "mic"
                        }
                    }
                },
                {
                    "prefix": {
                        "title": {
                            "value": "jord"
                        }
                    }
                }
            ]
        }
    }
}

И ожидаемый результат

"hits": [
      {
        "_index": "prefix",
        "_type": "_doc",
        "_id": "1",
        "_score": 4.0,
        "_source": {
          "title": "Nike shoes are worn by Michael Jordan"
        }
      },
      {
        "_index": "prefix",
        "_type": "_doc",
        "_id": "2",
        "_score": 4.0,
        "_source": {
          "title": "Michael Jordan wears shoes from Nike"
        }
      }
1 голос
/ 06 апреля 2020

Match_phrase_prefix

Возвращает документы, содержащие слова предоставленного текста, в том же порядке, что и предоставленный. Последний термин предоставленного текста обрабатывается как префикс, соответствующий любым словам, начинающимся с этого термина.

Таким образом, "Nik shoe Mi c Jord" будет выполнять поиск по фразе только для Jord и токенов также должен появиться в том же порядке.

Для поиска фразы по всем токенам используйте edge n грамм

Токенайзер edge_ngram сначала разбивает текст на слова всякий раз, когда встречается с одним из списка указанных символов затем он генерирует N-граммы каждого слова, где начало N-граммы привязано к началу слова.

Отображение

{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 2,  --> size of tokens
          "max_gram": 10,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
       "title":{
         "type": "text",
         "analyzer": "my_analyzer"
       }
    }
  }
}

Документы:

 [
      {
        "_index" : "index80",
        "_type" : "_doc",
        "_id" : "6RTKTXEBLqTvxU9z8bl3",
        "_score" : 1.0,
        "_source" : {
          "title" : "Nike shoes are worn by Michael Jordan"
        }
      },
      {
        "_index" : "index80",
        "_type" : "_doc",
        "_id" : "6hTLTXEBLqTvxU9zIrks",
        "_score" : 1.0,
        "_source" : {
          "title" : "Michael Jordan wears shoes from Nike"
        }
      },
      {
        "_index" : "index80",
        "_type" : "_doc",
        "_id" : "6xTLTXEBLqTvxU9zQbm4",
        "_score" : 1.0,
        "_source" : {
          "title" : "Mike Jordan"
        }
      },
      {
        "_index" : "index80",
        "_type" : "_doc",
        "_id" : "7BTLTXEBLqTvxU9zbLkT",
        "_score" : 1.0,
        "_source" : {
          "title" : "Nike is owned by Michael Jordan"
        }
      }
    ]

Запрос:

{
  "query": {
    "match": {
      "title": {
        "query": "Nik shoe Mic Jord",
        "operator": "and"  --> all tokens are needed
      }
    }
  }
}

Результат:

[
      {
        "_index" : "index80",
        "_type" : "_doc",
        "_id" : "6RTKTXEBLqTvxU9z8bl3",
        "_score" : 3.2434955,
        "_source" : {
          "title" : "Nike shoes are worn by Michael Jordan"
        }
      },
      {
        "_index" : "index80",
         "_type" : "_doc",
        "_id" : "6hTLTXEBLqTvxU9zIrks",
        "_score" : 3.1820722,
        "_source" : {
          "title" : "Michael Jordan wears shoes from Nike"
        }
      }
    ]

Для слова "майкл" с min-грамма: 2 и max-грамм: 5 генерируются следующие токены

{
      "token" : "Mi",
      "start_offset" : 23,
      "end_offset" : 25,
      "type" : "word",
      "position" : 13
    },
    {
      "token" : "Mic",
      "start_offset" : 23,
      "end_offset" : 26,
      "type" : "word",
      "position" : 14
    },
    {
      "token" : "Mich",
      "start_offset" : 23,
      "end_offset" : 27,
      "type" : "word",
      "position" : 15
    },
    {
      "token" : "Micha",
      "start_offset" : 23,
      "end_offset" : 28,
      "type" : "word",
      "position" : 16
    },
    {
      "token" : "Michae",
      "start_offset" : 23,
      "end_offset" : 29,
      "type" : "word",
      "position" : 17
    },
    {
      "token" : "Michael",
      "start_offset" : 23,
      "end_offset" : 30,
      "type" : "word",
      "position" : 18
    }

размер токена от 2 до 5 слов, поэтому важен выбор минимального и максимального грамма. Большая разница приведет к тому, что ваш индекс будет раздут, а небольшая разница может привести к тому, что документы не будут соответствовать

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