Elasticsearch Полнотекстовый поиск и точное совпадение - PullRequest
0 голосов
/ 04 июня 2018

Elasticsearch Mapping

PUT testindex
{
  "settings": {
    "analysis": {
            "filter": {},
            "tokenizer": {
              "my_tokenizer": {
                  "type": "ngram",
                  "min_gram": 3,
                  "max_gram": 3,
                  "token_chars": []
                }
            },
            "analyzer": {
                "my_analyzer": {
                  "tokenizer": "my_tokenizer",
                  "filter": ["lowercase"]
                },
                "hiphen_analyzer": {
                    "tokenizer": "whitespace",
                    "filter": ["lowercase"]
                }
            }
        }
  },
    "mappings": {
      "test": {
        "properties": {
          "catch_all": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "store": true,
                            "ignore_above": 256
                        },
                        "raw": {
                            "type": "text",
                            "store": true,
                            "analyzer": "hiphen_analyzer",
                            "search_analyzer": "whitespace"
                        },
                        "ngrams": {
                          "type": "text",
                          "store": true,
                          "analyzer": "my_analyzer"
                        }
                    }
          },
          "hostname": {
            "type": "text",
            "copy_to": "catch_all"
          }
        }
      }
    }
}

Документы

POST testindex/test
{
"hostname": "server-testing-01"
}
POST testindex/test
{
"hostname": "Dell Poweredge 111"
}

У меня есть имена серверов, такие как "server-testing-01", "server-testing-02", "Dell Poweredge Server".

Создано отображение вasticsearch с одним полем с именем хоста как" text "и copy_to field" catch_all ".

На данный момент будет скопировано только одно поле" hostname ", но другие поля также будут скопированыto catch_all field.

Существует глобальное поле поиска, которое помогает клиентам искать эти имена хостов и другие данные.

  1. При поиске "test" в результатах должно быть указано "server-testing-01", "server-testing-02".При поиске «power» результаты должны иметь «Dell Poweredge Server».При поиске «edge» результаты должны иметь «Dell Poweredge Server»
  2. При поиске точного результата «server-testing-01» должен содержаться только один результат.

edit:В настоящее время пробовал пользовательский анализатор ngram, который дает правильные результаты для некоторых частичных поисков не всех.

Может ли какой-нибудь орган, как добиться частичного поиска, а также точного поиска вasticsearch?

1 Ответ

0 голосов
/ 04 июня 2018

Самый простой способ достичь второго пункта, так как вы уже решили первый пункт, это обернуть ваш существующий запрос в логический запрос и поместить существующий запрос и новый запрос термина в условие must с minimum_should_match 1.Таким образом, он предоставит вам второй вариант.Если вам нужен рабочий пример, вам нужно предоставить свое сопоставление, один или два документа в качестве образца и свой запрос в данный момент.

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

PUT testindex
{
  "settings": {
    "analysis": {
      "analyzer": {
        "keyword_lowercase": {
          "tokenizer": "keyword",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "test": {
      "properties": {
        "hostname": {
          "type": "text",
          "analyzer": "keyword_lowercase"
        }
      }
    }
  }
}

GET testindex/_search
{
  "query": {
    "wildcard": {
      "hostname": {
        "value": "*test*"
      }
    }
  }
}

GET testindex/_search
{
  "query": {
    "wildcard": {
      "hostname": {
        "value": "*dell*power*"
      }
    }
  }
}

GET testindex/_search
{
  "query": {
    "wildcard": {
      "hostname": {
        "value": "*edge*"
      }
    }
  }
}

В общем, вы можете использовать ребра-нграммы, но это не будет охватывать пример edge, так как они начинаются с начала,Вы можете использовать ngrams, но max 3 недостаточно, и будут случаи, которые вы пропустите.При таком подходе вы охватите практически все.Что вам нужно сделать на уровне приложения, это для заданного вами ввода: 1. строчные буквы 2. оберните ввод подстановочными знаками

Примеры:

  • Dell -> *dell*
  • SERVER -> *server*
  • DELL POWER -> *dell power*

Будьте осторожны, хотя в некоторых случаях вы все равно пропустите Пример:

  • server testing -> *server testing*

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

  • server testing -> *server*testing*, который будет работать

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

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

...