Как выполнить полнотекстовый поиск по числовым полям в ElasticSearch?

вопрос:

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

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

пример.

настройка:

curl -XPUT http://localhost:9200/test/items/1 -d '{accountId : 12341234, name:"Bob"}'
curl -XPUT http://localhost:9200/test/items/2 -d '{accountId : 980987, name:"Marry"}'
curl -XPUT http://localhost:9200/test/items/3 -d '{accountId : 234234, name:"Daniel"}'

цель:

найти accountId с номером 4.

что я сделал.

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

запросы:

curl -XPOST "http://localhost:9200/test/items/_search" -d '{
  "query": {
    "term": {
      "accountId": "4"
    }
  }
}'

curl -XPOST "http://localhost:9200/test/items/_search" -d '{
  "query": {
    "query_string": {
      "query": "4"
    }
  }
}'

выход:

{
    "took": 0,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 0,
        "max_score": null,
        "hits": []
    }
}

2 ответов


Я предлагаю вам использовать токенизатор ngram для этой цели.

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

curl -XPUT localhost:9200/test?pretty=true -d '{
  "settings":{
    "analysis":{
      "analyzer":{
        "my_ngram_analyzer":{
          "tokenizer":"my_ngram_tokenizer"
        }
      },
      "tokenizer":{
        "my_ngram_tokenizer":{
          "type":"nGram",
          "token_chars":[
            "letter",
            "digit"
          ]
        }
      }
    }
  }
}'

подробнее о Ngram Tokenizer здесь.

затем вы должны определить следующее сопоставление:

curl -XPUT localhost:9200/test/items/_mapping?pretty=true -d '{
  "items":{
    "properties":{
      "accountId":{
        "analyzer":"my_ngram_analyzer",
        "type":"string"
      },
      "name":{
        "type":"string"
      }
    }
  }
}'

причина "accountId" является "строкой" в том, что токенизатор Ngram не работает на числовом поля.

Теперь вы можете запросить индекс :

curl -XGET localhost:9200/test/_search?pretty=true -d'
{
  "query": {
    "query_string": {
      "default_field": "accountId",
      "query": "4"
    }
  }
}'

вы можете найти здесь сценарий bash, который я использовал для его тестирования.

NB: конечно, это просто демо о том, как вы можете использовать Ngram Tokenizer. Надеюсь, это поможет


создать мульти-поле, которое будет содержать поле номер, а также строкой для поиска

PUT /test/items/_mapping
{
  "items" : {
    "properties" : {
      "accountId" : {
        "type" : "multi_field",
          "fields" : {
            "numeric" : {
              "type" : "integer",
              "index" : "not_analyzed"
            },
            "text" : {
              "type" : "string",
              "index" : "analyzed"
            }
          }
        }
      }
    }
}

проверить отображение:

GET /test/items/_mapping

выход

{
   "test": {
      "mappings": {
         "items": {
            "properties": {
               "accountId": {
                  "type": "integer",
                  "index": "no",
                  "fields": {
                     "numeric": {
                        "type": "integer"
                     },
                     "text": {
                        "type": "string"
                     }
                  }
               }
            }
         }
      }
   }
}

Поместите свои данные в эластичный поиск.

теперь вы можете выполнить поиск как строка, но вы получите результат как номер:

GET /test/items/_search
{
  "query": {
    "query_string": {
      "default_field": "accountId.text",
      "query": "*4*"
    }
  }
}

выход

{
   "took": 15,
   "timed_out": false,
   "_shards": {
      "total": 4,
      "successful": 4,
      "failed": 0
   },
   "hits": {
      "total": 2,
      "max_score": 1,
      "hits": [
         {
            "_index": "test",
            "_type": "items",
            "_id": "3",
            "_score": 1,
            "_source": {
               "accountId": 234234,
               "name": "Daniel"
            }
         },
         {
            "_index": "test",
            "_type": "items",
            "_id": "1",
            "_score": 1,
            "_source": {
               "accountId": 12341234,
               "name": "Bob"
            }
         }
      ]
   }
}