Elasticsearch: найти совпадение подстроки, точное совпадение и только при наличии совпадения - PullRequest
0 голосов
/ 04 августа 2020

Я хочу выполнить такой тип запроса, чтобы запрос отображал вывод тогда и только тогда, когда все слова в запросе присутствуют в данной строке в виде строки или запроса Например -

let text = "garbage can"

поэтому, если я запрошу

«мусор»

, он должен вернуть «мусорное ведро»

, если я запрошу

«мусорный контейнер»

, он должен вернуть «мусорный бак»

, но если я запрошу

"мусор b"

он ничего не должен возвращать

Я пробовал использовать подстроку , а также соответствует , но они оба не совсем помогли мне.

Ответы [ 2 ]

0 голосов
/ 04 августа 2020

Вы можете использовать токенизатор Edge N-грамм для индексации ваших данных. У вас также могут быть собственные token_chars в последней версии 7.8!

Более подробную информацию смотрите в документации: https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-edgengram-tokenizer.html

0 голосов
/ 04 августа 2020

Думаю, вы хотите выполнить запрос на префикс . попробуйте следующий запрос префикса :

GET /test_index/_search
{
  "query": {
    "prefix": {
      "my_keyword": {
        "value": "garbage b"
      }
    }
  }
}

Однако производительность такого типа запроса префикса не очень хороша.

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

PUT /test_index
{
  "settings": {
    "index": {
      "number_of_shards": "1",
      "analysis": {
        "filter": {
          "autocomplete_filter": {
            "type": "edge_ngram",
            "min_gram": "1",
            "max_gram": "20"
          }
        },
        "analyzer": {
          "autocomplete": {
            "filter": [
              "lowercase",
              "autocomplete_filter"
            ],
            "type": "custom",
            "tokenizer": "keyword"
          }
        }
      },
      "number_of_replicas": "1"
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "analyzer": "autocomplete",
        "type": "text"
      },
      "my_keyword": {
        "type": "keyword"
      }
    }
  }
}

Во-вторых, вставьте данные в этот индекс:

PUT /test_index/_doc/1
{
  "my_text": "garbage can",
  "my_keyword": "garbage can"
}

Запрос с «мусором c»

GET /test_index/_search
{
  "query": {
    "term": {
      "my_text": "garbage c"
    }
  }
}

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.45802015,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.45802015,
        "_source" : {
          "my_text" : "garbage can",
          "my_keyword" : "garbage can"
        }
      }
    ]
  }
}

Запрос с «мусором b»

GET /test_index/_search
{
  "query": {
    "term": {
      "my_text": "garbage b"
    }
  }
}

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

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

GET /test_index/_search
{
  "query": {
    "wildcard": {
      "my_keyword": {
        "value": "*garbage c*"
      }
    }
  }
}

Новая часть редактирования

Я не уверен, действительно ли я хочу, чтобы вы действительно захотели на этот раз ....

В любом случае, попробуйте использовать следующие _mapping и запросы:

1. Создать индекс

PUT /test_index
{
  "settings": {
    "index": {
      "max_ngram_diff": 50,
      "number_of_shards": "1",
      "analysis": {
        "filter": {
          "autocomplete_filter": {
            "type": "ngram",
            "min_gram": 1,
            "max_gram": 51,
            "token_chars": [
              "letter",
              "digit"
            ]
          }
        },
        "analyzer": {
          "autocomplete": {
            "filter": [
              "lowercase",
              "autocomplete_filter"
            ],
            "type": "custom",
            "tokenizer": "keyword"
          }
        }
      },
      "number_of_replicas": "1"
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "analyzer": "autocomplete",
        "type": "text"
      },
      "my_keyword": {
        "type": "keyword"
      }
    }
  }
}

2. Вставьте некоторые данные smaple

PUT /test_index/_doc/1
{
  "my_text": "test garbage can",
  "my_keyword": "test garbage can"
}

PUT /test_index/_doc/2
{
  "my_text": "garbage",
  "my_keyword": "garbage"
}

3. Запрос

GET /test_index/_search
{
  "query": {
    "term": {
      "my_text": "bage c"
    }
  }
}

Обратите внимание:

  1. Этот индекс поддерживает только строку с максимальной длиной 50. В противном случае вы необходимо изменить max_ngram_diff, min_gram и max_gram
  2. Требуется много памяти для построения индекса реверсирования
...