Я хочу использовать нечеткое сопоставление по запросу, но с точными совпадениями, отображаемыми в верхней части результатов.
Я пробовал следующее.
$return = $this->_client->search( array( 'index' => self::INDEX, 'type' => self::TYPE, 'body' => array( 'query' => array( 'bool' => array( 'must' => array( 'multi_match' => array( 'query' => $query, 'fields' => array('name', 'brand', 'description'), 'boost' => 10, ), 'fuzzy_like_this' => array( 'like_text' => $query, 'fields' => array('name', 'brand', 'description'), 'fuzziness' => 1, ), ), ), ), 'size' => '5000', ), ) );
Это не работает из-за неправильной ошибки запроса.
Есть идеи?
Я закончил тем, что не использовал нечеткое сопоставление для решения моей проблемы и пошел с использованием ngram's.
/** * Map - Create a new index with property mapping */ public function map() { $params['index'] = self::INDEX; $params['body']['settings'] = array( 'index' => array( 'analysis' => array( 'analyzer' => array( 'product_analyzer' => array( 'type' => 'custom', 'tokenizer' => 'whitespace', 'filter' => array('lowercase', 'product_ngram'), ), ), 'filter' => array( 'product_ngram' => array( 'type' => 'nGram', 'min_gram' => 3, 'max_gram' => 5, ), ) ), ) ); //all the beans $mapping = array( '_source' => array( 'enabled' => true ), 'properties' => array( 'id' => array( 'type' => 'string', ), 'name' => array( 'type' => 'string', 'analyzer' => 'product_analyzer', 'boost' => '10', ), 'brand' => array( 'type' => 'string', 'analyzer' => 'product_analyzer', 'boost' => '5', ), 'description' => array( 'type' => 'string', ), 'barcodes' => array( 'type' => 'string' ), ), ); $params['body']['mappings'][self::TYPE] = $mapping; $this->_client->indices()->create($params); } public function search($query) { $return = $this->_client->search( array( 'index' => self::INDEX, 'type' => self::TYPE, 'body' => array( 'query' => array( 'multi_match' => array( 'query' => $query, 'fields' => array('id', 'name', 'brand', 'description', 'barcodes'), ), ), 'size' => '5000', ), ) ); $productIds = array(); if (!empty($return['hits']['hits'])) { foreach ($return['hits']['hits'] as $hit) { $productIds[] = $hit['_id']; } } return $productIds; }
Результат – именно то, что я искал. Он строит совпадения, основанные на том, сколько части ngram имеет в нем поисковый запрос.
Отказ от ответственности, я не php-парень, но у меня есть некоторые подсказки к вашему запросу:
$return = $this->_client->search( array( 'index' => self::INDEX, 'type' => self::TYPE, 'body' => array( 'query' => array( 'bool' => array( 'should' => array( array( 'multi_match' => array( 'query' => $query, 'fields' => array('name', 'brand', 'description'), 'boost' => 10, ), ), array( 'fuzzy_like_this' => array( 'like_text' => $query, 'fields' => array('name', 'brand', 'description'), 'fuzziness' => 1, ), ), ), ), ), 'size' => '5000', ), ) );
Переход на это должен сделать так, чтобы только один из запросов должен совпадать, а не оба. Вы можете прочитать о запросе bool здесь: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html