Home/How to use elastic search in yii2

How to use elastic search in yii2

Published On: 24 June 2016.By .
  • Product & platform Engineering

Elastic Search can be implemented in yii2 easily. You need to setup server and elastic search before to use.

After elastic search setup, you need to install the yii2 extension

https://github.com/yiisoft/yii2-elasticsearch/blob/master/docs/guide/README.md

Configure in common/main.php file

'components' => [
   'elasticsearch' => [
       'class' => 'yii\elasticsearch\Connection',
       'nodes' => [
    	   ['http_address' => '127.0.0.1:9200'],
      	   // configure more hosts if you have a cluster
       ],
  ],
  
]

elasticsearch_logo-600x123

Creating index and mapping

Since it is not always possible to update ElasticSearch mappings incrementally, it is a good idea to create several static methods in your model that deal with index creation and updates. Here is one example of how this can be done.

Class Book extends yii\elasticsearch\ActiveRecord
{
    public static function index(){
        return "Catalog"
    }
    
    public static function type(){
        return "Book";
    }

    /**
     * @return array This model's mapping
     */
    public static function mapping()
    {
        return [
            static::type() => [
                'properties' => [
                    'id'             => ['type' => 'long'],
                    'name'           => ['type' => 'string'],
                    'author_name'    => ['type' => 'string', "index"=>"not_analyzed"],
                    'publisher_name' => ['type' => 'string', "index"=>"not_analyzed"],
                    'created_at'     => ['type' => 'long'],
                    'updated_at'     => ['type' => 'long'],
                    'status'         => ['type' => 'long'],
                    'suppliers'      => [
                         'type'      => 'nested',
                         'properties' => [
                               'id'  => ['type' => 'long'],
                               'name' => ['type' => 'string', 'index' => 'not_analyzed'],
                         ]
                    ]
                ]
            ],
        ];
    }

    /**
     * Set (update) mappings for this model
     */
    public static function updateMapping()
    {
        $db = static::getDb();
        $command = $db->createCommand();
        $command->setMapping(static::index(), static::type(), static::mapping());
    }

    /**
     * Create this model's index
     */
    public static function createIndex()
    {
        $db = static::getDb();
        $command = $db->createCommand();
        $command->createIndex(static::index(), [
            'settings' => [ 'index' => ['refresh_interval' => '1s'] ],
            'mappings' => static::mapping(),
            //'warmers' => [ /* ... */ ],
            //'aliases' => [ /* ... */ ],
            //'creation_date' => '...'
        ]);
    }

    /**
     * Delete this model's index
     */
    public static function deleteIndex()
    {
        $db = static::getDb();
        $command = $db->createCommand();
        $command->deleteIndex(static::index(), static::type());
    }

    public static function updateRecord($book_id, $columns){
       try{
            $record = self::get($book_id);
            foreach($columns as $key => $value){
                 $record->$key = $value;
            }
            
            return $record->update();
        }
        catch(\Exception $e){
            //handle error here
            return false;
        }
    }
    
    public static function deleteRecord($book_id)
    {
        try{
            $record = self::get($book_id);
            $record->delete();
            return 1;
        }
        catch(\Exception $e){
            //handle error here
            return false;
        }
    }

    public static function addRecord(Book $book){
        $isExist = false;
        
        try{
            $record = self::get($book->id);
            if(!$record){
                $record = new self();
                $record->setPrimaryKey($book->id);
            }
            else{
                $isExist = true;
            }
        }
        catch(\Exception $e){
            $record = new self();
            $record->setPrimaryKey($book->id);
        }

        $suppliers = [
             ['id' => '1', 'name' => 'ABC'],
             ['id' => '2', 'name' => 'XYZ'],             
        ];

        $record->id   = $book->id;
        $record->name = $book->name;
        $record->author_name = $image->author_name;
        $record->status = 1;
        $record->suppliers = $suppliers;

        try{ 
            if(!$isExist){
                $result = $record->insert();
            }
            else{
                $result = $record->update();
            }
        }
        catch(\Exception $e){
            $result = false;
            //handle error here
        }
        
        return $result;
    }
}

By using above class, you can create index and mapping. Also you can add records in Book index.

Querying the data by yii\elasticsearch\Query

use yii\elasticsearch\Query;

$query = new Query();
$query->source('*');
$query->from(Book::index(), Book::type())->limit(10);

//build and execute the query
$command = $query->createCommand();
$rows = $command->search(); // this way you get the raw output of elasticsearch.

Adding aggregation in query

$query->addAggregation("status", "terms", array("field"=>"status" , "order" => ['_term' => "asc"]));
$query->addAggregation("author_name", "terms", array("field"=>"author_name",'size' => 25));

Adding filters in query

$filters  = [];
$filters['bool']['must'][]['term']['status']  = 1;

//nested filters
$filter = [];
$filter['nested']['path'] = 'suppliers';
$filter['nested']['query']['bool']['must'][]['match']['suppliers.name'] = 'XYZ';
$filter['nested']['query']['bool']['must'][]['match']['suppliers.id']  = 1;
$filters['bool']['must'][] = $filter;

if($filters){
   $query->query($filters);
}

Adding sorting in results

$query->orderBy = ['id' => ['order' => 'desc']];

Paging and render results

try{
    $pages  = new Pagination(['totalCount' => $query->count() , "defaultPageSize" => $limit]);
    $offset = ($page-1)*$limit;
    $query->offset($offset)->limit($limit);
        	
    $command = $query->createCommand();
    $rows = $command->search();
}
catch(\Exception $e){
   $message = $e->getMessage();
   return $this->render("/site/error",['name'=> "Search Results",'message' => "Search service is currently not working, Please try again later."]);
}
        
 $aggregations = $rows['aggregations'];
 $provider = new ArrayDataProvider([
     'allModels' => $rows['hits']['hits'],
      	  'pagination' => [
        	'pageSize' => $limit,
          ],
 ]);

 

Related content

We Love Conversations

Say Hello
Go to Top