Я хочу иметь возможность хранить объект 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
Тем не менее, я не вижу способа обеспечить это отображение внутри модели. Документация расширения ничего не говорит об этом.
Итак, мой вопрос: нужно ли мне это вообще, и если да, то как?
Ценю все отзывы.
Я предполагаю, что ваша модель \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"}
}
}
}
Обратите внимание на три вещи:
geo_point
,string
, Это также позволит им быть массивами строк.$model->primaryKey = '123'
). В противном случае для вашей модели ES будет установлен внутренний идентификатор: AVDXmfJ3Ou7LzqD1DDMj
а также есть поле id, которое не очень удобно.Я рекомендую вам поближе взглянуть на сопоставления — они очень важны, когда речь идет о настройке того, как именно анализируются строки.
ОБНОВИТЬ: Вы действительно не описываете отображение в вашей модели. Делайте это в процессе миграции — аналогично созданию таблиц в SQL.
Если вы используете 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"],
],
],
]);
}
}
Позже вам просто нужно будет вызывать этот метод в любое время, когда вы захотите применить новое отображение.