#php #elasticsearch #fuzzy-search
#php #elasticsearch #нечеткий поиск
Вопрос:
Я хочу использовать нечеткое сопоставление в запросе, но с точными совпадениями, отображаемыми в верхней части результатов.
Я пробовал следующее.
$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',
),
)
);
Это не работает из-за ошибки неправильного запроса.
Есть идеи?
Комментарии:
1. Теперь я понимаю, чего вы хотите :). Вы пробовали sense или инструмент, позволяющий написать запрос, который вам нравится, в чистом json? Я обнаружил, что это намного проще, если сначала заставить его работать непосредственно с elasticsearch с помощью sense, а затем перевести его в NEST (который я использую в .NET).
2. Нет, пока нет. Я пойду посмотрю на sense. Это раздражает, я бы подумал, что точные совпадения действительно окажутся на вершине по умолчанию.
3. Я думаю, что ваш запрос кажется немного странным. Когда я читаю это, кажется, что у вас должно быть совпадение с несколькими совпадениями и fuzzy_like_this, это должно быть should. Смотрите мой ответ.
Ответ №1:
В итоге я не использовал нечеткое сопоставление для решения своей проблемы и пошел с использованием ngram.
/**
* 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 содержит в себе поисковый запрос.
Комментарии:
1. классная штука, я думаю, что это может быть лучшим подходом, чем нечеткий, поэтому спасибо, что поделились.
Ответ №2:
Отказ от ответственности, я не специалист по 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
Комментарии:
1. Спасибо, я все еще получаю ошибку » QueryParsingException [[products] [_na] запрос неверно сформирован, нет поля после start_object]; }]», «статус»: 400}». Ошибка.