Синонимы и подстроки


(Березин Юрий) #1

Доброго времени суток!
Настраиваю elasticSearch для поиска по базе мероприятий. Поиск нужен по полному слову и по подстрокам тоже. Настроил анализаторы и маппинг:

{ 
"template" : "*", 
"settings" : { 
		"analysis" : {
			"analyzer" : {
				"russian_indexer" : {
					"type" : "custom",
					"tokenizer" : "rus_nGram",
					"filter" : [
						"russian_morphology",
						"rus_snow",
						"rus_stop",
						"rus_delim",
						"lowercase"
					]
				},
				"russian_searcher" : {
					"type" : "custom",
					"tokenizer" : "letter",
					"filter" : [
						"russian_morphology",
						"rus_snow",
						"rus_stop",
						"rus_delim",
						"lowercase"
					]
				}
			},
			"tokenizer" : {
				"rus_nGram" : {
					"type": "nGram",
					"min_gram": 3,
					"max_gram": 8
				}
			},
			"filter" : {
            "rus_snow" : {
                "type" : "snowball",
                "language" : "Russian"
            },
				"rus_stop": {
					"type": "stop",
					"language": "_russian_"
				},
				"rus_delim": {
					"type": "word_delimiter"
				}
        }
		} 
	}, 
"mappings" : { 
    "_default_" : { 
        "_all" : { "enabled" : false }, 
			"properties" : { 
            "content" : {
					"type" : "text",
					"analyzer" : "russian_indexer",
                "search_analyzer" : "russian_searcher"
				},
				"title" : {
					"type" : "text",
					"analyzer" : "russian_indexer",
                "search_analyzer" : "russian_searcher"
				},
				"full_info" : {
					"type" : "text",
					"analyzer" : "russian_indexer",
                "search_analyzer" : "russian_searcher"
				},
				"short_info" : {
					"type" : "text",
					"analyzer" : "russian_indexer",
                "search_analyzer" : "russian_searcher"
				},
				"role" : {
					"type" : "text",
					"analyzer" : "russian_indexer",
                "search_analyzer" : "russian_searcher"
				},
				"name" : {
					"type" : "text",
					"analyzer" : "russian_indexer",
  indent preformatted text by 4 spaces                  "search_analyzer" : "russian_searcher"
				},
				"created_at" : {
					"type": "date"
				}
        } 
    } 
} 
}

Настроил морфологию и ngram.
Из кода php обращаю к Эластику:

$params = [
    'index' => ['shows'],
    'type' => ['show'],
    'explain' => true,
    'body' => [
        'query' => [
            'function_score' => [
  				'query' => [
  					"dis_max" => [
  						"queries" => [
  							[
  								'multi_match' => (object)[
  									'query' =>  $searchQuery,
  									'type' => 'best_fields',
  									'fields' => ['name^10', 'short_info^5', 'full_info', 'content', 'title^10', 'role^5'],
  									"boost" => 10
  								]
  							],
  							[
  								'multi_match' => (object)[
  									'query' =>  $searchQuery,
  									'fields' => ['name^10', 'short_info^5', 'full_info', 'content', 'title^10', 'role^5'],
  									"analyzer" => "russian_searcher",
  									"boost" => 1
  								]
  							]
  						],
  					]
  				]
            ],
        ]
    ]
];

Но результаты меня не удовлетворяют. Мне нужно, чтобы boost=10 применялся только тогда, когда произошло совпадение по синониму.
Если я правильно понимаю, мне нужно создать один анализатор для ngram, а один - для морфологии. Сейчас, если я хочу найти "Красную шапочку" по запросу "Красный", он находит подстроку "Красн" и дает ей boost=10 но в explain'е пишет, что это подстрока (как nGram).

Надеюсь на помощь, вывод самого эластика могу предоставить


Языковые анализаторы, синонимы, nGram
(Igor Motov) #2

Для того чтобы понять, почему это не работает, вам надо разобраться с тем, как работают фильтры в анализаторе. Я бы посоветовал начать с прочтения Dealing with Human Language в руководстве.

Вкратце, для того что бы искать и по подстроке и по корням слов, не надо сваливать все в один анализатор. Надо создать два анализатора, проиндексировать слова каждым в отдельные поля (multi-fields), и искать сразу по нескольким полям с boost-ом.


Поиск с морфологией и без
(system) #3

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.