#php #laravel #elasticsearch
Вопрос:
Вкратце, в Laravel я использую пакет elasticsearch_php. У меня есть несколько продуктов, которые индексируют их в эластичном поиске. Когда я хочу выполнить поиск в индексированных продуктах со строкой запроса, я получаю сообщение об ошибке:
[вложенный] вложенный объект по пути [категории] не имеет вложенного типа». Вот мой код.
У меня есть файл миграции CreateProductSearchIndex
для эластичных индексов продукта, который выглядит следующим образом, и определяет тип категорий как nested
public function up() {
$this->elastic->indices()->create([
'index' => 'product',
'body' => [
'mappings' => [
'properties' => [
'name' => [
'type' => 'text',
'analyzer' => 'persian'
],
'slug' => [
'type' => 'keyword'
],
//....
'categories' => [
'type' => 'nested',
'properties' => [
'id' => [
'type' => 'long'
],
'name' => [
'type' => 'text',
'analyzer' => 'persian'
],
'parent_id' => [
'type' => 'long'
]
]
]
]
]
]
]);
}
В методе я передаю id
продукт и индексирую продукт (добавляю его в elastic).
public function sync(int $id, string $sync = SyncEvent::SYNC_ALL): void
{
$product = $this->repository->product->find($id, false);
if ($product) {
$exists = $this->repository->search->exists(['id' => $product->id]);
if (!$exists) {
$this->elastic->index([
'id' => $product->id,
'body' => $this->getProduct($product, $sync),
]);
}
}
// ...
}
private function getProduct(Product $product, string $sync): array
{
$data = [];
if ($this->shouldSync($sync, ProductSyncEvent::SYNC_PRODUCT)) {
$data = $product->toArray([
'id', 'name', // ...
]);
// ...
$data['categories'] = $product->categoryHierarchy()->map->only(['id', 'name', 'parent_id'])->toArray();
}
return $data;
}
After indeces some products I can see them in elatic
result of getting product without query string
curl -u '<username>:<password>' -X GET "http://localhost:9200/product/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 1000
}
'
is like this:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "product",
"_type" : "_doc",
"_id" : "175",
"_score" : 1.0,
"_source" : {
"id" : 175,
"name" : "first product",
"categories" : [
{
"id" : 262,
"name" : "cat1",
"parent_id" : 251
},
{
"id" : 251,
"name" : "cat2",
"parent_id" : 0
}
]
}
}
]
}
}
It seems everything is right. But when I send requet with query string like:
curl -u '<username>:<password>' -X GET "http://localhost:9200/product/_search?pretty" -H 'Content-Type: application/json' -d'
{
"size": 1000,
"query": {
"nested" : {
"path" : "categories",
"query" : {
"bool" : {
"must" : [
{ "match" : {"categories.name" : "cat1"} }
]
}
}
}
}
}
'
Я получаю сообщение об ошибке, в котором говорится:
«причина»: «Не удалось создать запрос: [вложенный] вложенный объект по пути [категории] не имеет вложенного типа».
Здесь вы можете увидеть сопоставление данных:
curl -u '<username>:<password>' http://localhost:9200/product/_mapping?pretty
{
"product": {
"mappings": {
"properties": {
"categories": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"parent_id": {
"type": "long"
}
}
},
"id": {
"type": "long"
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
Я не знаю, что не так с моим кодом. Любая помощь-это любая помощь, которая ценится.
Комментарии:
1. перейдите на свой ES-сервер, например
localhost:9200/product
, чтобы проверить, правильно ли свойство создано как вложенное. Если это не так, попробуйте удалить и воссоздать индекс2. @apokryfos Я переиндексирую его снова и снова. Кроме того, я подумал, что, возможно, есть проблема с данными. поэтому я отбрасываю все продукты и индексирую только один.
3. отбросьте весь индекс. Если вы удалите все продукты, сопоставление все еще будет сохранено
4. @apokryfos Я использую это:
curl -u '<u>:<pass>' http://localhost:9200/product -XDELETE
. Я прав?5. Да, это снизило бы индекс. Затем после этого убедитесь, что миграция выполняется, прежде чем добавлять какие-либо документы, иначе индекс будет автоматически изменен