mawebcoder/laravel-elasticsearch

3.0.0 2023-12-07 07:14 UTC

This package is auto-updated.

Last update: 2024-09-11 07:12:10 UTC


README

使用Eloquent类似的查询构建器,你可以驯服这个野兽,无需担心Elasticsearch的复杂语法。

你可以使用这个包而不必深入研究Elasticsearch,通过不需要记住复杂的嵌套语法来节省时间。

依赖项

配置文件和Elasticsearch迁移日志

为了能够保存与迁移相关的日志并自定义你的配置,你需要运行以下命令

php artisan vendor:publish --tag=elastic

然后迁移你的数据库

php artisan migrate

配置

发布配置文件后,你会看到以下内容


return [
    'index_prefix' => env('APP_NAME', 'elasticsearch'),
    'host' => 'https://',
    'port' => 9200,
    'reindex_migration_driver' => "sync", //sync or queue,
    "reindex_migration_queue_name" => 'default',
    'base_migrations_path' => app_path('Elasticsearch/Migrations'),
    'base_models_path' => app_path('Elasticsearch/Models'),
    "username" => env('ELASTICSEARCH_USERNAME', null),
    'password' => env('ELASTICSEARCH_PASSWORD', null)
];

ORM

此包为Laravel中的文档工作添加了ORM功能,使得它更容易使用,就像我们在Laravel中看到的那样。我们将随着进程的推进了解更多。让我们深入探讨。

模型

为了能够更有效地与我们的文档进行关联,我们需要为每个索引创建一个模型。与我们在Laravel中看到的模型相似,这大大简化了与数据库通信的工作。

创建模型

php artisan elastic:make-model <model-name>

默认情况下,你的模型基础路径位于app/Elasticsearch/Models目录,但你可以在config/elasticsearch.php文件中定义自己的基础路径。

你的所有模型都必须继承自BaseElasticsearchModel类。这是一个抽象类,它强制你实现返回模型索引名的getIndex方法。

public function getIndex():string 

{
    return 'articles';
}

我们使用此方法的返回值在迁移中创建你想要的索引。

如果你想通过你在配置文件中定义的前缀来获取你的索引名

$model->getIndexWithPrefix();

迁移

正如你所知,Elasticsearch使用映射来定义其文档的结构,这可能在原始形式中看起来有些困难。为了简化这个过程,我们使用迁移使其更容易。在定义模型后,你必须创建一个迁移来注册你希望的字段。你的所有迁移都必须继承自BaseElasticMigration抽象类。

创建新的迁移

php artisan elastic:make-migration <migration-name>

默认情况下,你的迁移基础路径位于app/Elasticsearch/Migrations目录,但你可以在config/elasticsearch.php文件中定义自己的基础路径。

<?php

//app/Elasticsearch/Migrations

use Mawebcoder\Elasticsearch\Migration\BaseElasticMigration
use App\Elasticsearch\Models\EArticleModel;


return new class extends BaseElasticMigration {

public function getModel():string 
{

    return EArticleModel::class;
}


 public function schema(BaseElasticMigration $mapper): void
    {
        $mapper->integer('id');
        $mapper->string('name');
        $mapper->boolean('is_active');
        $mapper->text('details');
        $mapper->integer('age');
        $mapper->object('user',function($BaseElasticMigration $mapper){
                                        return $mapper->string('name')
                                        ->object('values',function($mapper){
                                                return $mapper->bigInt('id);
                                        })
                                        });
    }

};

不幸的是,该包无法自动找到你的迁移路径。要引入迁移路径,将以下示例代码放在你的一个提供者中

use Mawebcoder\Elasticsearch\Facade\Elasticsearch;

 public function register(): void
    {
        Elasticsearch::loadMigrationsFrom(__DIR__ . '/../Elastic/Migrations');
        Elasticsearch::loadMigrationsFrom(__DIR__ . '/../App/Migrations');
    }

查看迁移状态

php artisan elastic:migrate-status

迁移迁移并创建你的索引映射

php artisan elastic:migrate

重置所有迁移(此命令仅在所有迁移中运行down方法)

php artisan elstic:migrate --reset

删除所有索引并重新注册它们

php artisan elastic:migrate --fresh

回滚迁移

php artisan elastic:migrate-rollback

默认情况下,此命令仅回滚一次迁移。如果你想自己确定步骤

php artisan elastic:migrate-rollback --step=<number>

字段类型

整数

$this->integer('age');

字符串(关键词)

$this->string('name');

对象

$this->object('categories',function($mapper){
    return $mapper->string('name','teylor')
-           >integer('parentM_id',22)
            ->object('sequences',function($mapper){
                    return $mapper->bigInt('id');
            })
})

布尔值

$this->boolean('is_active');

小整数(短)

$this->smallInteger('age');

大整数(长)

$this->bigInteger('income');

双精度浮点数

$this->double('price');

浮点数

$this->float('income');

字节型整数(字节)

$this->tinyInt('value');

文本

$this->text(field:'description',fieldData:true);

日期时间

$this->datetime('created_at');

编辑索引映射

有时您需要修改您的映射。为此,您需要添加一个新的迁移

php artisan elastic:make-migration <alter migration name>

<?php

use Mawebcoder\Elasticsearch\Migration\BaseElasticMigration;
use Mawebcoder\Elasticsearch\Models\EArticleModel;
use Mawebcoder\Elasticsearch\Migration\AlterElasticIndexMigrationInterface;

return new class extends BaseElasticMigration implements AlterElasticIndexMigrationInterface {
    public function getModel(): string
    {
        return EArticleModel::class;
    }

    public function schema(BaseElasticMigration $mapper): void
    {
        $mapper->dropField('name');
        $mapper->boolean('new_field');//add this field to 
    }

    public function alterDown(BaseElasticMigration $mapper): void
    {
        $mapper->string('name');
        $mapper->dropField('new_field');
    }
};

如您所见,我们在迁移中实现了AlterElasticIndexMigrationInterface接口。然后在alterDown方法中,我们编写了我们的回滚场景。最后,迁移您的迁移

php artisan elastic:migrate

动态映射

默认情况下,Elasticsearch可以检测您在映射中未引入的字段类型,并自动定义其类型。该软件包默认禁用了此功能。要激活它,请在您的迁移中执行以下操作

protected bool $isDynamicMapping = true;

查询构建器

就像Laravel一样,它允许您通过使用一系列预定义的方法来创建复杂和简单的查询,这个软件包也使用了这个功能,为您提供类似的经验。

存储记录

$eArticleModel=new EArticleModel();

$eArticleModel->name='mohammad';

$eArticleModel->id=2;

$eArticleModel->is_active=true;

$eArticleModel->user=[
    'name'=>'komeil',
    'id'=>3
];

$eArticleModel->text='your text';

$eArticleModel->age=23;

$eArticleModel->save();
  • 注意:如果您没有传递映射中存在的任何字段,我们默认将其设置为null

存储多个记录(批量插入)

$users = [
    [
        id => 1,
        name => 'Mohsen',
        is_active => true,
        text => 'your text',
        age => 25
    ],
    [
        id => 2,
        name => 'Ali',
        is_active => true,
        text => 'your text',
        age => 20
    ]
];

$result=EUserModel::newQuery()->saveMany($users);

有时,由于错误,某些项目可能无法保存在数据库中。您可以像下面这样进行检查

if($result->hasError()){
    $notImportedItems=$result->getNotImportedItems();
}

$importedItems=$result->getImportedItems();

如果您想在出现任何错误时回滚事务,请将$withTransaction参数设置为true

$result=EUserModel::newQuery()->saveMany(items:$users,withTransaction:true);

此操作将从数据库中删除导入的项目。

查找记录

$eArticleModel=new EArticleModel();

$result=$eArticleModel->find(2);

删除记录

$eArticleModel=new EArticleModel();

$result=$eArticleModel->find(2);

$result?->delete();

条件

等于

$eArticleModel
->where('id',2)
->orWhere('id',2)
->get();

不等于

$eArticleModel
->where('id','<>',2)
->orWhere('id','<>',10)
->get();
  • 注意:不要在text字段上使用=<>运算符,因为我们在这两个运算符中使用了term。在text字段中,您需要使用likenot like运算符代替

大于

$eArticleModel->where('id','>',10)->orWhere('id','>=',20)->get();

小于

$eArticleModel->where('id','<',2)->orWhere('id',null)->first();

类似

$eArticleModel->where('name','like','foo')->orWhere('name','not like','foo2')->get();

whereTerm

有时您想在文本中搜索特定的短语。在这种情况下,您可以执行以下操作

$eArticleModel->whereTerm('name','foo')->orWhereTerm('name','<>','foo2')->get();

whereIn

$eArticleModel->whereIn('id',[1,2])->orWhereIn('age',[23,26])->first();

whereNotIn

$eArticleModel->whereNotIn('id',[1,2])->orWhereNotIn('id',[26,23])->get();

whereBetween

$eArticleModel->whereBetween('id,[1,2])->orWhereBetween('age',[26,27])->first();

whereNotBetween

$eArticleModel->whereNotBetween('id',[1,2])->orWhereNotBetween('id,'26,27])->get();

whereNull

$eArticleModel->whereNull('id')->orWhereNull('name')->first();

whereNotNull

$eArticleModel->whereNotNull('id')->orWhereNotNull()->first();

链式调用

$eArticleModel=new EArticleModel();

$eArticleModel
->where('name','<>','mohammad')
->orWhere('name,'komeil')
->whereNotIn('id,[1,2,3])
->where('name','like','value')
->whereBetween('id',[10,13])
->whereNotBetween('id',[1,2])
->whereTerm('name','foo')
->get();

模糊搜索

注意:模糊搜索仅适用于文本字段

$eArticleModel=new EArticleModel();

$eArticleModel
->whereFuzzy('name','mawebcoder',fuzziness:3)
->get();

您可以根据需要更改模糊度值

获取纯查询

$eArticleModel->where('id','like','foo')->dd();

更新记录


$eArticleModel=new EArticleModel();

$result=$eArticleModel->find(2);

$result?->update([
    'name'=>'elastic',
    //...
]);

批量更新

$eArticleModel=new EArticleModel();

$eArticleModel
->where('name','<>','mohammad')
->update([
    'name'=>'elastic',
    //...
]);

批量删除

$eArticleModel=new EArticleModel();

$eArticleModel
->where('name','<>','mohammad')
->delete();

获取一定数量的记录(限制)

$eArticleModel=new EArticleModel();

$eArticleModel
->where('name','<>','mohammad')
->take(10)
->get();

偏移量

$eArticleModel=new EArticleModel();

$eArticleModel
->where('name','<>','mohammad')
->take(10)
->offset(5)
->get();

选择

$eArticleModel=new EArticleModel();

$eArticleModel
->where('name','<>','mohammad')
->select('name,'age','id')
->get();

排序

$eArticleModel=new EArticleModel();

$eArticleModel
->where('name','<>','mohammad')
->select('name,'age')
->orderBy('age','desc')
->get();

  • 注意:不要在text字段上使用orderBy,因为文本不适合在Elasticsearch中进行排序操作。但如果您想强制对文本进行排序,请设置fielddata=true
$this->text(field:"description",fielddata:true) 

通过添加上述行,您可以使用文本作为可排序的和在聚合中,但fielddata在索引时使用大量内存

获取特定字段的值

$name=$eArticleModel->name;

嵌套搜索

首先,我们需要在我们的迁移中定义object类型


"category":{
            "name":"elastic",
            "id":2
          }

$mapper->object('categories',[
            'name'=>self::TYPE_STRING,
            'id'=>self::TYPE_BIGINT
        ]);
$eArticleModel
->where('categories.name')->first();

如果您有如下所示的多维对象


"categories":[
           {
            "name":"elastic",
            "id":2
           },
           {
            "name":"mohammad",
            "id":3
           }


            ]

定义您的映射如下

$mapper->object('categories',[
            'name'=>self::TYPE_STRING,
            'id'=>self::TYPE_BIGINT
        ]);
$eArticleModel
->where('categories.name')->first();

按ID销毁

$eArticleModel->destroy([1,2,3]);

嵌套查询

为了创建复杂和嵌套的查询,您可以使用构建器的嵌套功能。您的查询嵌套没有限制

$model=Model::newQuery()
->where('name','john')
->where(function($model){
        return $model->where('age',22)
        ->orWhere(function($model){
        return $model->whereBetween('range',[1,10]);
        })
})->orWhere(function($model){
    return $model->where('color','red')
    ->orWhereIn('cars',['bmw','buggati'])
})->get()

请注意,您需要从闭包中返回查询,否则它将被忽略

chunk

为了更好地管理您的内存使用,您可以使用chunk方法

$model=Model::newQuery()
->where('name','mohammad')
->chunk(100,function(Collection $collection){
    //code here
})

聚合

默认情况下,所有相关数据也将返回。如果您只想在结果中使用聚合,请使用take(0)来防止在您的请求中过载数据

计数

$eArticleModel
->where('categories.name')
->orWhere('companies.title','like','foo')
->count();

$eArticleModel
->bucket('languages','languages-count')
->get();

$aggregations=$eArticleModel['aggregations'];

默认情况下,桶方法返回最多2147483647条记录,如果您想更改它

$eArticleModel
->bucket('languages','languages-count',300) //returns 300 records maximum
->get();

最小值

$model->min('year')->get()

最大值

$model->max('year')->get()

平均值

$model->avg('year')->get()

总和

$model->sum('year')->get()

唯一

有时您需要根据某个标准检索仅基于唯一记录

$model->where('category','elastic')->unique('name');

分组

为了根据某个标准对数据进行分组

$model->where('category','elastic')->groupby(field:'age',sortField:'category',direction:'desc');

分页

$eArticleModel
->where('categories.name')
->orWhere('companies.title','like','foo')
->paginate()

默认情况下,分页方法每页15个项目进行分页,但您可以进行更改

$eArticleModel
->where('categories.name')
->paginate(20)

结果将类似于以下内容

[
    "data"=>[...],
    'total_records' => 150,
    'last_page' => 12,
    'current_page' => 9,
    'next_link' => localhost:9200?page=10,
    'prev_link' => localhost:9200?page=8,
]

inRandomOrder

有时您需要从Elasticsearch中获取随机数据

$eArticleModel
->where('categories.name')
->inRandomOrder()
->take(10)
->get()

与文档交互

按名称删除索引


Elasticsearch::dropIndexByName($model->getIndexWithPrefix())

检查索引是否存在


Elasticsearch::hasIndex($model->getIndexWithPrefix())

获取所有索引


Elasticsearch::getAllIndexes()

按模型删除索引


Elasticsearch::setModel(EArticle::class)->dropModelIndex()

获取所有模型字段


Elasticsearch::setModel(EArticle::class)->getFields()

获取模型映射


Elasticsearch::setModel(EArticle::class)->getMappings()

即将推出

  • 直方图
  • 定义归一化和分词器
  • 原始查询