How to use ActiveRecord with yii2-elasticsearch?

Hi, I’m trying to store a log of CUD operations in ElasticSearch (being myself a newcomer to ES) from a Yii2 program. I’ve created a model following the instructions here: https://github.com/yiisoft/yii2-elasticsearch/tree/master/docs/guide , with this code:


namespace app\models;


use yii\elasticsearch\ActiveRecord;


class RegistroOplog extends ActiveRecord

{

   public function attributes()

   {

  	return ['id', 'uid', 'accion', 'descripcion', 'modulo', 'clase', 'url', 'detalles', 'fecha', 'ip'];

   }

   

   public static function mapping()

   {

  	return [

     	static::type() => [

        	'properties' => [

           	'id' => ['type' => 'long'],

           	'uid'=> ['type' => 'long'],

           	'accion' => ['type' => 'byte'],

           	'descripcion' => ['type' => 'string'],

           	'modulo' => ['type' => 'string'],

           	'clase' => ['type' => 'string'],

           	'url' => ['type' => 'string'],

           	'detalles' => ['type' => 'object'],

           	'fecha' => ['type' => 'date'],

           	'ip' => ['type' => 'string'],

        	]

     	],

  	];

   }


   public static function updateMapping()

   {

  	$db = static::getDb();

  	$command = $db->createCommand();

  	$command->setMapping(static::index(), static::type(), static::mapping());

   }


   public static function createIndex()

   {

  	xdebug_break();

  	$db = static::getDb();

  	$command = $db->createCommand();

  	$command->createIndex(static::index(), [

     	//'settings' => [ /* ... */ ],

     	'mappings' => static::mapping(),

     	//'warmers' => [ /* ... */ ],

     	//'aliases' => [ /* ... */ ],

     	//'creation_date' => '...'

  	]);

   }


   public static function deleteIndex()

   {

  	$db = static::getDb();

  	$command = $db->createCommand();

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

   }   

   

   public function getUsuarios()

   {

  	return $this->hasMany(SeguridadUsuarios::className(), ['uid' => 'id'])->orderBy('id');

   }

   

   public static function activo($query)

   {

  	$query->andWhere(['activo' => 1]);

   }   

}

As far as I understand, the first thing to do is to create the map and index, either in Kibana directly, or in PHP code. I opted to do it in PHP:


   public function actionIndex()

   {

  	try {

     	\app\models\RegistroOplog::createIndex();

     	//Yii::$app->op->add('EJEMPLO DE ALTA', 'MODULO_EJEMPLO');

  	}

  	catch (Exception $ex) {

     	QA::exception($ex);

  	}

  	return $this->render('index');

   }

However, I get an error 500 from ES, and in its log I get this error:

[font="Courier New"]java.lang.ClassCastException: java.base/java.util.ArrayList cannot be cast to java.base/java.util.Map[/font]

After googling the error I read that in some cases it is caused by an empty map, but mine is not empty. So I’m really stuck here. Has anybody used this extension? Any hint? Thanks a lot in advanced.

P.S. If I do the call to the save() directly, I get a 400 (it seems that the 400 error is a complaint about not having map/index yet).

Oh well, I have run the query in Kibana and, my bug: "string" should be "text" in the type mappings. Working fine now.

1 Like

I had this same problem. Your solution made me think it was a configuration error. I noticed you had the settings parameter commented out. Sure enough, that was it. You can’t pass an empty array, whether mappings or settings. This should probably be updated in the docs to avoid this problem for others.