panda843/laravel-elasticsearch

在Laravel中使用Elasticsearch作为数据库来检索Eloquent模型和执行聚合操作。

v6.5.313 2023-02-24 07:15 UTC

README

在Laravel中使用Elasticsearch作为数据库来检索Eloquent模型和执行聚合操作。

像使用Eloquent一样构建Elasticsearch查询,并获取模型实例,还有一些额外的功能

  • 使用queryfilterpostFilter查询类型
  • 执行地理搜索
  • 在您的数据上构建和执行复杂的聚合操作
  • 使用Elasticsearch的scroll API检索大量结果

版本

根据您的Elasticsearch版本,您可以使用此包的以下版本

设置

将Elasticsearch连接配置添加到database.php

'elasticsearch' => [
    'driver'   => 'elasticsearch',
    'host'     => 'localhost',
    'port'     => 9200,
    'database' => 'your_es_index',
    'username' => 'optional_es_username',
    'password' => 'optional_es_username',
    'suffix'   => 'optional_es_index_suffix',
]

创建或更新您的base Model.php类以重写newEloquentBuilder()newBaseQueryBuilder()

/**
 * Create a new Eloquent builder for the model.
 *
 * @param  \Illuminate\Database\Query\Builder  $query
 * @return \Illuminate\Database\Eloquent\Builder|static
 */
public function newEloquentBuilder($query)
{
    switch ($this->getConnectionName()) {
        case static::getElasticsearchConnectionName():
            $builder = new ElasticsearchEloquentBuilder($query);
            break;

        default:
            $builder = new Illuminate\Database\Eloquent\Builder($query);
    }

    return $builder;
}

/**
 * Get a new query builder instance for the connection.
 *
 * @return \Illuminate\Database\Query\Builder
 */
protected function newBaseQueryBuilder()
{
    $connection = $this->getConnection();

    switch ($this->getConnectionName()) {
        case static::getElasticsearchConnectionName():
            $builder = new ElasticsearchQueryBuilder($connection, $connection->getQueryGrammar(), $connection->getPostProcessor());
            break;

        default:
            $builder = new Illuminate\Database\Query\Builder($connection, $connection->getPostProcessor());
    }

    return $builder;
}

搜索

现在您可以开始对数据进行搜索了。查询将查找与您的模型所在的数据库表同名的Elasticsearch索引。

$documents = MyModel::newElasticsearchQuery()
              ->where('date', '>', Carbon\Carbon::now())
              ->get();

聚合

可以通过与直接查询Elasticsearch类似的方法向查询中添加聚合,使用嵌套函数而不是嵌套数组。aggregation()方法接受三个或四个参数

  1. 用于聚合的键
  2. 聚合类型,如'filter'或'terms'
  3. (可选)一个回调或数组,提供聚合的选项
  4. (可选)一个函数,允许您提供进一步的子聚合
$myQuery = MyModel::newElasticsearchQuery()
             ->aggregation(
                 // The key of the aggregation (used in the Elasticsearch response)
                 'my_filter_aggregation',

                 // The type of the aggregation
                 'filter',

                 // A callback providing options to the aggregation, in this case adding filter criteria to a query builder
                 function ($query) {
                     $query->where('lost', '!=', true);
                     $query->where('concierge', true);
                 },

                 // A callback specifying a sub-aggregation
                 function ($builder) {
                     // A simpler aggregation, counting terms in the 'status' field
                     $builder->aggregation('my_terms_aggregation', 'terms', ['field' => 'status']);
                 }
             );

$results = $myQuery->get();
$aggregations = $myQuery->getQuery()->getAggregationResults();

地理查询

您可以通过从地理点距离过滤搜索结果,或仅包含在给定边界内的结果来过滤搜索结果,传递的参数格式与直接查询Elasticsearch时使用的格式相同。

$withinDistance = MyModel::newElasticsearchQuery()
                    ->whereGeoDistance('geo_field', [$lat, $lon], $distance);

$withinBounds= MyModel::newElasticsearchQuery()
                 ->whereGeoBoundsIn('geo_field', $boundingBox);

Scroll API

您可以使用滚动搜索来检索大量结果。而不是返回一个Collection,您将获得一个PHP 生成器函数,您可以迭代它,其中每个值都是一个来自Elasticsearch的单个结果的模型。

$documents = MyModel::newElasticsearchQuery()
               ->limit(100000)
               ->usingScroll()
               ->get();

// $documents is a Generator
foreach ($documents as $document){
  echo $document->id;
}

控制台

此包附带以下命令,用作实用程序或作为部署过程的一部分。

映射和别名

migrate:mappings期间创建新索引时,该命令将自动创建一个别名,通过删除日期字符串来根据迁移名称创建。例如,迁移2018_08_03_095804_users.json将创建别名users

在第一次迁移中,migrate:mappings命令还将别名切换到最新的索引映射。上述操作仅在别名不存在时才会发生。

未来的迁移需要您使用--swap选项。