ElasticSearch ищет с дефисом внутри слова

Я хотел бы попросить о помощи. Я хочу искать слова внутри заголовка и содержимого. Вот структура

'body' => array(
  'mappings' => array(
    'myindex' => array(
      '_source' => array(
        'enabled' => true
      ),
      'properties' => array(
        'Title' => array(
          'type'  => 'string',
          'fields'=> array(
            'raw' => array(
               'type'  => 'string',
               'index' => 'not_analyzed'
              )
            )
          ),
          'Content' => array(
            'type'  => 'string'
          ),
          'Image' => array(
             type'      => 'string',
             'analyzer'  => 'standard'
         )
       )
     )
   )
 )

И строка запроса выглядит так, где я хочу найти 15-g внутри текста, такого как 15-game:

"query" : {
  "query_string": {
    "query": "*15-g*",
    "fields": [ "Title", "Content" ]
  }
}

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

Я уже посмотрел:

ElasticSearch — поиск с дефисами

ElasticSearch — поиск с дефисами в имени

ElasticSearch — поиск с дефисами в имени

Но я не могу заставить работать это со мной.

Что действительно интересно, так это то, что если я ищу 15-g (15пробел-пробелg), он возвращает результат.

Огромное спасибо заранее!


person Sensini    schedule 08.07.2015    source источник


Ответы (2)


Также добавьте поле .raw в поле Content и выполните поиск по полям .raw:

{
  "query": {
    "query_string": {
      "query": "*15-g*",
      "fields": [
        "Title.raw",
        "Content.raw"
      ]
    }
  }
}

Везде, где у вас есть пробел в тексте, который вы хотите найти, и вы хотите, чтобы этот пробел соответствовал вашим полям, его нужно экранировать (с помощью \). Кроме того, в любое время, когда у вас есть заглавные буквы и подстановочные знаки, и вы хотите сопоставить их с полями .raw, вам нужно установить lowercase_expanded_terms на false, потому что по умолчанию этот параметр равен true, и строка поиска будет строчной (она будет искать laptop - black) :

{
  "query": {
    "query_string": {
      "query": "*Laptop\\ -\\ Black*",
      "lowercase_expanded_terms": false, 
      "fields": [
        "Title.raw",
        "Content.raw"
      ]
    }
  }
}
person Andrei Stefan    schedule 08.07.2015
comment
Спасибо @Andrei, все работает! Что если я хочу найти два слова или более ex. Ноутбук - Черный Допустим, у меня есть Ноутбук с Windows - Черный, и я хочу найти его с Ноутбуком - Черный. Большое спасибо еще раз. С уважением. - person Sensini; 09.07.2015
comment
Везде, где у вас есть пробел в тексте, который вы хотите найти, и вы хотите соответствовать вашим полям, его нужно экранировать. Кроме того, в любое время, когда у вас есть заглавные буквы и подстановочные знаки, и вы хотите сопоставить их с полями .raw, вам нужно установить lowercase_expanded_terms в false, потому что это будет строчной строкой поиска. Обновил мой ответ. - person Andrei Stefan; 09.07.2015
comment
Большое спасибо @Andrei. Я ценю ваши усилия. Все работает, как вы объяснили. :) - person Sensini; 09.07.2015
comment
Не могли бы вы дать мне представление, как я могу сделать поиск нечувствительным к регистру? С уважением - person Sensini; 09.07.2015

В elasticsearch 5 вы можете определить собственный анализатор с настройкой фильтра. Вот примеры кодов:

PUT test1
{
  "settings" : {
    "analysis" : {
      "analyzer" : {
        "myAnalyzer" : {
          "type" : "custom",
          "tokenizer" : "whitespace",
          "filter" : [ "dont_split_on_numerics" ]
        }
      },
      "filter" : {
        "dont_split_on_numerics" : {
          "type" : "word_delimiter",
          "preserve_original": true,
          "generate_number_parts" : false
        }
      }
    }
  },
  "mappings": {
    "type_one": {
      "properties": {
        "title": { 
          "type": "text",
          "analyzer": "standard"
        }
      }
    },
    "type_two": {
      "properties": {
        "raw": { 
          "type": "text",
          "analyzer": "myAnalyzer"
        }
      }
    }
  }
}

Пожалуйста, знайте, что я установил

"сохранить_оригинал": правда "сгенерировать_число_частей"

Так что строка "2-345-6789" останется как есть. Dash — зарезервированное слово в elasticsearch. Без указанной выше настройки стандартный токенизатор будет генерировать «2», «345» и «6789». Итак, теперь вы можете использовать поиск по шаблону, т.е.

"5-67"

чтобы получить результат.

POST test1/type_two/1
{
  "raw": "2-345-6789"
}

GET test1/type_two/_search
{
  "query": {
    "wildcard": {
      "raw": "*5-67*"
    }
  }
}

Подробную информацию можно найти по адресу эластичный поисковый токенфильтр

person Yang Young    schedule 13.07.2017