Elasticsearch — настройки сопоставления индексов для точного и частичного совпадения

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

Если у меня есть такой документ

{"name":"Galapagos Islands"}

Я хочу получить этот результат для обоих следующих запросов

1) Частичное соответствие

{
    "query": {
        "match": {
            "name": "ga"
        }
    }
}

2) Точное соответствие

{
    "query": {
        "term": {
            "name": "Galapagos Islands"
        }
    }
}

С настройкой, которая у меня есть в настоящее время. Я могу добиться частичного соответствия части. Но точное совпадение не дает результатов. Пожалуйста, найдите ниже настройки, с которыми я проиндексировал.

{
  "mappings": {
        "islands": {
            "properties": {
                "name":{
                    "type": "string",
                    "index_analyzer": "autocomplete",
                    "search_analyzer": "search_ngram"
                }
            }
        }
    },

  "settings":{
    "analysis":{
      "analyzer":{
        "autocomplete":{
          "type":"custom",
          "tokenizer":"standard",
          "filter":[ "standard", "lowercase", "stop", "kstem", "ngram" ] 
        },
        "search_ngram": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": "lowercase"
        }
      },
      "filter":{
        "ngram":{
          "type":"ngram",
          "min_gram":2,
          "max_gram":15
        }
      }
    }
  }
}

Каков правильный способ точного и частичного сопоставления поля?

ОБНОВЛЕНИЕ

После воссоздания индекса с настройками, указанными ниже. Мои сопоставления выглядят так

curl -XGET 'localhost:9200/testing/_mappings?pretty'
{
  "testing" : {
    "mappings" : {
      "islands" : {
        "properties" : {
          "name" : {
            "type" : "string",
            "index_analyzer" : "autocomplete",
            "search_analyzer" : "search_ngram",
            "fields" : {
              "raw" : {
                "type" : "string",
                "analyzer" : "my_keyword_lowercase_analyzer"
              }
            }
          }
        }
      }
    }
  }
}

Мои настройки индексации приведены ниже.

{
  "mappings": {
        "islands": {
            "properties": {
                "name":{
                    "type": "string",
                    "index_analyzer": "autocomplete",
                    "search_analyzer": "search_ngram",
                    "fields": {
                      "raw": {
                          "type": "string",
                          "analyzer": "my_keyword_lowercase_analyzer"
                      }
                    }
                }
            }
        }
    },

  "settings":{
    "analysis":{
      "analyzer":{
        "autocomplete":{
          "type":"custom",
          "tokenizer":"standard",
          "filter":[ "standard", "lowercase", "stop", "kstem", "ngram" ] 
        },
        "search_ngram": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": "lowercase"
        },
        "my_keyword_lowercase_analyzer": {
          "type": "custom",
          "filter": ["lowercase"],
          "tokenizer": "keyword"
        }
      },
      "filter":{
        "ngram":{
          "type":"ngram",
          "min_gram":2,
          "max_gram":15
        }
      }
    }
  }
}

И со всем вышеперечисленным, когда я запрашиваю вот так

curl -XGET 'localhost:9200/testing/islands/_search?pretty' -d '{"query": {"term": {"name.raw" : "Galapagos Islands"}}}'
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

И мой документ это

curl -XGET 'localhost:9200/testing/islands/1?pretty'
{
  "_index" : "testing",
  "_type" : "islands",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source":{"name":"Galapagos Islands"}
}

person chaithu    schedule 14.10.2015    source источник
comment
Ваше сопоставление, тестовые данные и запросы работают на меня. Вы уверены, что проверили это должным образом?   -  person Andrei Stefan    schedule 14.10.2015
comment
Что вы получите, если запустите GET /index_name/islands/_search { "fielddata_fields": [ "name" ] } ?   -  person Andrei Stefan    schedule 14.10.2015
comment
После вашего обновления тикета это имеет смысл :-). И мой ответ ниже стоит.   -  person Andrei Stefan    schedule 14.10.2015
comment
@AndreiStefan Пожалуйста, найдите вывод запроса fielddatafields выше   -  person chaithu    schedule 14.10.2015
comment
Мой запрос к fielddata_fields имел смысл с вашим первоначальным сообщением. Теперь, когда вы обновили его правильным запросом, он мне больше не нужен. Попробуйте мое предложение ниже.   -  person Andrei Stefan    schedule 14.10.2015


Ответы (1)


Добавьте подполе к вашему свойству name, которое должно быть not_analyzed. Или, если вы заботитесь о строчных/верхних регистрах, токенизатор keyword вместе с фильтром lowercase.

Это должно индексировать Galapagos как есть, а не модификации. Затем вы можете выполнить term поиск.

Например, анализатор keyword вместе с фильтром lowercase:

    "my_keyword_lowercase_analyzer": {
      "type": "custom",
      "filter": [
        "lowercase"
      ],
      "tokenizer": "keyword"
    }

И отображение:

        "properties": {
            "name":{
                "type": "string",
                "index_analyzer": "autocomplete",
                "search_analyzer": "search_ngram",
                "fields": {
                    "raw": {
                        "type": "string",
                        "analyzer": "my_keyword_lowercase_analyzer"
                    }
                }
            }
        }

Используемый запрос:

{
    "query": {
        "term": {
            "name.raw": "galapagos islands"
        }
    }
}

Итак, вместо того, чтобы использовать одно и то же поле — name — вы должны использовать name.raw (подполе).

person Andrei Stefan    schedule 14.10.2015
comment
Привет @Andrei, Спасибо, что быстро ответили на мой запрос. Я воссоздал свой индекс с указанными выше настройками. Но я не могу найти термин Галапагосские острова. Я использую следующий запрос: {query: {term: {name: Galapagos Islands}}} - person chaithu; 14.10.2015
comment
Привет Андрей, я все перепроверил и добавил к своему вопросу. Мне кажется, это не работает :-( - person chaithu; 14.10.2015
comment
Виноват. Мой анализатор будет строчными значениями. У вас есть два варианта: использовать "galapagos islands" в вашем поиске (нижний регистр): "term": { "name.raw": "galapagos islands" } - или изменить сопоставление на что-то вроде этого: "fields": { "raw": { "type": "string", "index": "not_analyzed" } } и использовать "Galapagos Islands" при поиске: "term": { "name.raw": "Galapagos Islands" } - person Andrei Stefan; 14.10.2015