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

Как это сделать, чтобы он не возвращал документ при запросе John Oxford ?

Мое отображение, настройки, образец документа и запрос данных о студентах приведены ниже.

< Сильного > Отображение

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 - частичный матч против "Джона" и "Доу"
  • 1983-12-04 - соответствует DOB
  • johndoe - частичное совпадение по электронной почте
  • лань - совпадение фамилии
1
Lily 16 Апр 2020 в 10:53

1 ответ

Лучший ответ

Чтобы реализовать частичный поиск, вы должны добавить конкретный autocomplete analyzer в обязательные текстовые поля и реализовать конкретный 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. Для вашего варианта использования cross-field должен быть лучшим:

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" 
    }
  }
}
2
Lupanoide 16 Апр 2020 в 19:19