Расширение Yii2 Elasticsearch — как мне обрабатывать сопоставление типов?

Я хочу иметь возможность хранить объект json в моем индексе ES. Вот пример того, что я пытаюсь сохранить (это сериализованная модель, тело запроса, которое отправляется в ES):

"{"id":218,"name":"Test2","category_id":1,"address":"Pushkin street","phone":null,"site":null,"location":{"lat":64,"lon":70},"city":"Heaven","description":"Super company","tags":["#test1","#test2"]}"

Когда я пытаюсь сохранить его (через расширение, конечно), вот ошибка, которую возвращает ES:

"{"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"failed to parse [location]"}],"type":"mapper_parsing_exception","reason":"failed to parse [location]","caused_by":{"type":"illegal_argument_exception","reason":"unknown property [lat]"}},"status":400}"

Кажется, что я не могу сделать это без конкретного сопоставления типов, как в документах:
https://www.elastic.co/guide/en/elasticsearch/reference/1.4/mapping-object-type.html

Тем не менее, я не вижу способа обеспечить это отображение внутри модели. Документация расширения ничего не говорит об этом.
Итак, мой вопрос: нужно ли мне это вообще, и если да, то как?

Ценю все отзывы.

0

Решение

Я предполагаю, что ваша модель \yii\elasticsearch\ActiveRecord, Вам нужно будет описать его атрибуты:

public function attributes()
{
return [
'name',
'category_id',
'address',
'phone',
'site',
'location',
'city',
'description',
'tags'
];
}

Не забудьте настроить index() а также type(), В следующем примере type является my_address,

Тогда вам нужно создать индекс с правильное отображение поля. Вот как должно выглядеть ваше отображение:

"mappings" : {
"my_address" : {
"properties" : {
"name" : { "type" : "string"},
"category_id" : { "type" : "integer"},
"address" : { "type" : "string"},
"phone" : { "type" : "string"},
"site" : { "type" : "string"},
"location" : { "type" : "geo_point"},
"city" : { "type" : "string"},
"description" : { "type" : "string"},
"tags" : { "type" : "string"}
}
}
}

Обратите внимание на три вещи:

  1. Местоположение имеет тип geo_point,
  2. Теги объявлены как string, Это также позволит им быть массивами строк.
  3. Я не включил поле id. Если он уникален, я предлагаю вам установить идентификатор вашей модели yii на нужное значение ($model->primaryKey = '123'). В противном случае для вашей модели ES будет установлен внутренний идентификатор: AVDXmfJ3Ou7LzqD1DDMj а также есть поле id, которое не очень удобно.

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

ОБНОВИТЬ: Вы действительно не описываете отображение в вашей модели. Делайте это в процессе миграции — аналогично созданию таблиц в SQL.

1

Другие решения

Если вы используете ElasticSearch ActiveRecord, вы можете определить метод для setupMapping

Class BookIndex extends yii\elasticsearch\ActiveRecord
{
/**
* sets up the index for this record
*
*/
public static function setUpMapping()
{
$db = static::getDb();

//in case you are not using elasticsearch ActiveRecord so current class extends database ActiveRecord yii/db/activeRecord
// $db = yii\elasticsearch\ActiveRecord::getDb();

$command = $db->createCommand();

/*
* you can delete the current mapping for fresh mapping but this not recommended and can be dangrous.
*/

// $command->deleteMapping(static::index(), static::type());

$command->setMapping(static::index(), static::type(), [
static::type() => [
// "_id" => ["path" => "id", "store" => "yes"],
"properties" => [
'name'           => ["type" => "string"],
'author_name'    => ["type" => "string"],
'publisher_name' => ["type" => "string"],
'created_at'     => ["type" => "long"],
'updated_at'     => ["type" => "long"],
'status'         => ["type" => "long"],

],
],
]);
}
}

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

1

По вопросам рекламы [email protected]