Thanks for your response. Now I understand the difference between index and record. What I’m trying to do is:
I’ve created an index “users” in elasticsearch and I want to add all records from my database users table (fields are ‘id’, ‘name’, ‘email’) to this index (how to add record to a particular index if I have multiple indexes).
Want to create an autocomplete with substring highlighting using n-gram.
Here’s my updated model code (Full word is matching but substring is not matching):
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\elasticsearch\ActiveDataProvider;
use yii\elasticsearch\Query;
use yii\elasticsearch\QueryBuilder;
class Elastic extends \yii\elasticsearch\ActiveRecord
{
public function attributes()
{
return['id', 'name', 'email'];
}
public static function mapping()
{
return [
static::type() => [
'properties' => [
'id' => ['type' => 'integer'],
'name' => [
'type' => 'string',
"analyzer" => "autocomplete",
"search_analyzer" => "standard",
],
'email' => ['type' => 'string'],
]
],
];
}
/**
* 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('users', [
'settings' => [
'index' => [
"number_of_shards" => 1,
"number_of_replicas" => 1,
],
'analysis' => [
'analyzer' => [
"autocomplete" => [
"type" => "custom",
"tokenizer" => "standard",
"filter" => [ "lowercase", "autocomplete_filter" ],
],
],
'filter' => [
"autocomplete_filter" => [
"type" => "edge_ngram",
"min_gram" => 2,
"max_gram" => 15,
],
],
],
],
'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());
}
/**
* Search index
*/
public function Searches($value)
{
$search = $value['search'];
$query = new Query();
$db = Elastic::getDb();
$queryBuilder = new QueryBuilder($db);
$match = ['match' => ['name' =>$search]];
$query->query = $match;
$build = $queryBuilder->build($query);
$re = $query->search($db, $build);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => ['pageSize' => 10],
]);
return $dataProvider;
}
}
?>
And here is my controller code:
<?php
namespace app\controllers;
use app\models\Customer;
use app\models\Search;
use Yii;
use yii\web\Controller;
class ElasticController extends Controller
{
public function actionCreateIndex(){
$elastic = new Search();
if ($elastic->createIndex()) {
echo "Index created Successfully";
} else {
echo "Error";
}
}
public function actionSearch(){
$elastic = new Search();
$result = $elastic->Searches(Yii::$app->request->queryParams);
$query = Yii::$app->request->queryParams;
return $this->render('search', [
'searchModel' => $elastic,
'dataProvider' => $result,
'query' => $query['search'],
]);
}
}
?>
class Elastic extends \yii\elasticsearch\ActiveRecord
{
.
.
.
Yii creates an index with the name of its class, so "elastic" will be your index. You can override those methods and put the index and type name that you want.
Example:
class UserElastic extends \yii\elasticsearch\ActiveRecord
{
/**
* @inheritdoc
*/
public static function index()
{
return 'users';
}
/**
* @inheritdoc
*/
public static function type()
{
return 'user';
}
.
.
.
// the rest of your code
.
.
.
.
/**
* Create this model's index
*/
public static function createIndex()
{
$db = static::getDb();
$command = $db->createCommand();
$command->createIndex(static::index(), [
.
.
.
// the rest of your code
}
Now you have a index called users and a type called user.
For indexing just do a ->save(). It will be saved in the index users and type user.