Elasticsearch частичный запрос - PullRequest
1 голос
/ 16 апреля 2020

Я работаю с Elasticsearch v 7.3.1 и пытаюсь реализовать частичный поиск. Все поиски идут хорошо, но когда я запрашиваю " Джон Оксфорд ", "Джон" совпадает с документом, но во всем до "1043 *" нет " Оксфорд ". Но все равно показывает мне документ вместо того, чтобы показывать пустые результаты.

Как я могу это сделать, чтобы он не возвращал документ, когда мы запрашиваем Джон Оксфорд ?

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

Отображения

PUT student
{
  "settings": {
    "analysis": {
      "filter": {
        "autocomplete_filter": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 20
        }
      },
      "analyzer": {
        "autocomplete": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "autocomplete_filter"
          ]
        }
      }
    }
  }, "mappings" : {
      "properties" : {
        "DOB" : {
          "type" : "text"
        },
        "email" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "first_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "home_phone" : {
          "type" : "text"
        },
        "last_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "student_id" : {
          "type" : "text"
        }
      }
    }
}

Образец документа

POST student/_doc
{
    "DOB": "1983-12-04",
    "email": "johndoe@gmail.fr",
    "first_name": "john",
    "home_phone": 1242432,
    "last_name": "doe",
    "student_id": 28

}

Запрос

GET student/_search
{
  "query": {
    "multi_match": {
      "query": "john oxford",
      "type": "bool_prefix",
      "analyzer": "standard",
      "fields": [
        "first_name",
        "last_name",
        "email",
        "DOB",
        "home_phone",
        "student_id"
      ]
    }
  }
}

Ниже приведены результаты, которые я хочу

  • 1242 - частично соответствует home_phone
  • joh do - частичное совпадение с "John" и "Doe" "
  • 1983-12-04 - соответствует DOB
  • johndoe - частичное совпадение по электронной почте
  • doe - совпадение фамилии

1 Ответ

2 голосов
/ 16 апреля 2020

Для реализации частичного поиска вы должны добавить спецификацию c autocomplete analyzer к обязательным текстовым полям и реализовать спецификацию c search_analyzer, потому что вы используете фильтр edgengram - пожалуйста, прочитайте здесь и здесь для объяснения. Это удобнее, чем указывать анализатор во время запроса, как вы это сделали. Попробуйте:

PUT student
{
  "settings": {
    "analysis": {
      "filter": {
        "autocomplete_filter": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 20
        }
      },
      "analyzer": {
        "autocomplete": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "autocomplete_filter"
          ]
        }
      }
    }
  }, "mappings" : {
      "properties" : {
        "DOB" : {
          "type" : "text",
          "analyzer": "autocomplete",
          "search_analyzer": "standard"
        },
        "email" : {
          "type" : "text",
          "analyzer": "autocomplete",
          "search_analyzer": "standard",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "first_name" : {
          "type" : "text",
          "analyzer": "autocomplete",
          "search_analyzer": "standard",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "home_phone" : {
          "type" : "text",
          "analyzer": "autocomplete",
          "search_analyzer": "standard"
        },
        "last_name" : {
          "type" : "text",
          "analyzer": "autocomplete",
          "search_analyzer": "standard",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "student_id" : {
          "type" : "text"
        }
      }
    }
}

Затем, когда вы запрашиваете автозаполнение двух терминов, вы должны объединить их с помощью оператора and. Для вашего случая использования кросс-поле тип должен быть лучшим:

GET student/_search
{
  "query": {
    "multi_match" : {
      "query":      "John Oxford",
      "type":       "cross_fields",
      "fields": [
        "first_name",
        "last_name",
        "email",
        "DOB",
        "home_phone",
        "student_id"
      ],
      "operator":   "and" 
    }
  }
}
...