el-hendawy/laralestic

Laravel、Lumen 和原生 PHP Elasticseach & Opensearch 查询构建器,使用优雅的语法 ORM 构建复杂查询

v1.1.1 2023-06-20 22:07 UTC

This package is auto-updated.

Last update: 2024-09-10 17:56:10 UTC


README

Latest Stable Version Total Downloads License

Laravel、Lumen 和原生 PHP elasticseach 查询构建器,使用优雅的语法构建复杂查询

  • 通过替换数组查询为简单而优雅的语法,让您摆脱浪费时间。
  • 受 Laravel Eloquent 启发的 Elasticsearch 数据模型,包括类型和索引。
  • 可以自由地通过简单的 artisan 命令行工具进行创建、删除、映射和重新索引。
  • Lumen 框架支持。
  • 原生 PHP 和基于 composer 的应用程序支持。
  • 可作为 laravel scout 驱动程序使用。
  • 同时处理多个 elasticsearch 连接。
  • 基于 LengthAwarePagination 的出色分页。
  • 使用基于 laravel cache 的缓存层缓存查询。

要求

  • php >= 7.2

    查看 Travis CI 构建

  • laravel/laravel >= 8.* 或 laravel/lumen >= 8.* 或 composer application

安装

Laravel 安装

1) 使用 composer 安装包。
$ composer require el-hendawy/laralestic
2) 添加包服务提供者(< laravel 5.5)。
Omar\Laralestic\LaralesticServiceProvider::class
3) 添加包别名(< laravel 5.5)。
'ES' => Omar\Laralestic\Facades\ES::class
4) 发布。
$ php artisan vendor:publish --provider="Omar\Laralestic\LaralesticServiceProvider"

Lumen 安装

1) 使用 composer 安装包。
$ composer require el-hendawy/laralestic
2) 在 bootstrap/app.php 中添加包服务提供者。
$app->register(Omar\Laralestic\LaralesticServiceProvider::class);
3) 将包配置目录 vendor/el-hendawy/laralestic/src/config 复制到根目录中,与 app 目录并列。
4) 通过在 bootstrap/app.php 中取消注释此行使 Lumen 与外观协同工作。
$app->withFacades();

如果您不想启用 Lumen 外观的工作,您可以使用 app("es") 访问查询构建器。

app("es")->index("my_index")->type("my_type")->get();
# is similar to 
ES::index("my_index")->type("my_type")->get();

Composer 安装

您可以使用任何基于 composer 的应用程序安装包

1) 使用 composer 安装包。
$ composer require el-hendawy/laralestic
2) 创建连接。
require "vendor/autoload.php";
use Omar\Laralestic\Connection;
$connection = Connection::create([
    'servers' => [
        [
            "host" => '127.0.0.1',
            "port" => 9200,
            'user' => '',
            'pass' => '',
            'scheme' => 'http',
        ],
    ],
    
	// Custom handlers
	// 'handler' => new MyCustomHandler(),
    'index' => 'my_index',
    
    'logging' => [
        'enabled'   => env('ELASTIC_LOGGING_ENABLED',false),
        'level'     => env('ELASTIC_LOGGING_LEVEL','all'),
        'location'  => env('ELASTIC_LOGGING_LOCATION',base_path('storage/logs/elasticsearch.log'))
    ],  
]);
# access the query builder using created connection
$documents = $connection->search("hello")->get();

配置(Laravel & Lumen)

发布后,将创建两个配置文件。

  • config/es.php 其中您可以添加多个 elasticsearch 服务器。
# Here you can define the default connection name.
'default' => env('ELASTIC_CONNECTION', 'default'),
# Here you can define your connections.
'connections' => [
	'default' => [
	    'servers' => [
	        [
	            "host" => env("ELASTIC_HOST", "127.0.0.1"),
	            "port" => env("ELASTIC_PORT", 9200),
	            'user' => env('ELASTIC_USER', ''),
	            'pass' => env('ELASTIC_PASS', ''),
	            'scheme' => env('ELASTIC_SCHEME', 'http'),
	        ]
	    ],
	    
		// Custom handlers
		// 'handler' => new MyCustomHandler(),
		
		'index' => env('ELASTIC_INDEX', 'my_index')
	]
],
 
# Here you can define your indices.
 
'indices' => [
	'my_index_1' => [
	    "aliases" => [
	        "my_index"
	    ],
	    'settings' => [
	        "number_of_shards" => 1,
	        "number_of_replicas" => 0,
	    ],
	    'mappings' => [
	        'posts' => [
                'properties' => [
                    'title' => [
                        'type' => 'string'
                    ]
                ]
	        ]
	    ]
	]
]
  • config/scout.php 其中您可以使用包作为 laravel scout 驱动程序。

与控制台环境协同工作(Laravel & Lumen)

通过一些 artisan 命令,您可以执行一些任务,例如创建或更新设置、映射和别名。

注意,所有命令都带有 --connection=default 选项,您可以通过命令更改它。

以下都是可用的命令

列出服务器上的所有索引

$ php artisan es:indices:list
+----------------------+--------+--------+----------+------------------------+-----+-----+------------+--------------+------------+----------------+
| configured (es.php)  | health | status | index    | uuid                   | pri | rep | docs.count | docs.deleted | store.size | pri.store.size |
+----------------------+--------+--------+----------+------------------------+-----+-----+------------+--------------+------------+----------------+
| yes                  | green  | open   | my_index | 5URW60KJQNionAJgL6Q2TQ | 1   | 0   | 0          | 0            | 260b       | 260b           |
+----------------------+--------+--------+----------+------------------------+-----+-----+------------+--------------+------------+----------------+

创建在 es.php 配置文件中定义的索引

注意,创建操作会跳过已存在的索引。

# Create all indices in config file.
$ php artisan es:indices:create
# Create only 'my_index' index in config file
$ php artisan es:indices:create my_index 

更新在 es.php 配置文件中定义的索引

注意,更新操作更新索引设置、别名和映射,但不删除已索引的数据。

# Update all indices in config file.
$ php artisan es:indices:update
# Update only 'my_index' index in config file
$ php artisan es:indices:update my_index 

删除索引

使用此命令时要小心,您将丢失索引数据!

使用 --force 选项运行删除命令将跳过所有确认信息。

# Drop all indices in config file.
$ php artisan es:indices:drop
# Drop specific index on sever. Not matter for index to be exist in config file or not.
$ php artisan es:indices:drop my_index 

数据重新索引(零停机时间)

首先,为什么重新索引?

更改索引映射不进行数据重新索引不会反映出来,否则您的搜索结果将不会正确工作。

为了避免停机时间,您的应用程序应该使用索引 alias 而不是索引 name

索引 alias 是一个常量名称,应用程序应该使用它来避免更改索引名称。

假设我们想更改 my_index 的映射,以下是操作方法
  1. alias作为示例my_index_alias添加到my_index配置中,并确保应用程序可以正常工作。
"aliases" => [
    "my_index_alias"
]       
  1. 使用命令更新索引。
$ php artisan es:indices:update my_index
  1. 在配置文件中创建一个新的索引,例如my_new_index,并包含您的新映射。
$ php artisan es:indices:create my_new_index
  1. 使用命令将my_index中的数据重新索引到my_new_index中。
$ php artisan es:indices:reindex my_index my_new_index
# Control bulk size. Adjust it with your server.
$ php artisan es:indices:reindex my_index my_new_index --bulk-size=2000
# Control query scroll value.
$ php artisan es:indices:reindex my_index my_new_index --bulk-size=2000 --scroll=2m
# Skip reindexing errors such as mapper parsing exceptions.
$ php artisan es:indices:reindex my_index my_new_index --bulk-size=2000 --skip-errors 
# Hide all reindexing errors and show the progres bar only.
$ php artisan es:indices:reindex my_index my_new_index --bulk-size=2000 --skip-errors --hide-errors
  1. 在配置文件中从my_index移除my_index_alias别名,并添加到my_new_index中,然后使用命令更新。
$ php artisan es:indices:update

作为Laravel Scout驱动程序的使用

首先,按照Laravel Scout安装步骤进行操作。

您只需更新配置文件config/scout.php中的这些行。

# change the default driver to 'es'
	
'driver' => env('SCOUT_DRIVER', 'es'),
	
# link `es` driver with default elasticsearch connection in config/es.php
	
'es' => [
    'connection' => env('ELASTIC_CONNECTION', 'default'),
],

请参阅laravel Scout文档

Elasticsearch数据模型

每个索引类型都有一个对应的“模型”,用于与该类型交互。模型允许您查询类型或索引中的数据,以及向类型中插入新的文档。

基本用法
<?php
namespace App;
use Omar\Laralestic\Model;
class Post extends Model
{
        
    protected $type = "posts";
    
}

上述示例将使用默认连接和默认索引中的es.php。您可以在下一个示例中覆盖这两个参数。

<?php
namespace App;
use Omar\Laralestic\Model;
class Post extends Model
{
    
    # [optional] Default: default elasticsearch driver
    # To override default conenction name of es.php file.
    # Assumed that there is a connection with name 'my_connection'
    protected $connection = "my_connection";
    
    # [optional] Default: default connection index
    # To override default index name of es.php file.
    protected $index = "my_index";
    
    protected $type = "posts";
    
}
检索模型

一旦创建了一个模型及其相关的索引类型,您就可以开始从索引中检索数据。例如

<?php
use App\Post;
$posts = App\Post::all();
foreach ($posts as $post) {
    echo $post->title;
}
添加额外的约束

all方法将返回模型类型中的所有结果。每个Elasticsearch模型都作为查询构建器,您还可以向查询添加约束,然后使用get()方法检索结果

$posts = App\Post::where('status', 1)
               ->orderBy('created_at', 'desc')
               ->take(10)
               ->get();
检索单个模型
// Retrieve a model by document key...
$posts = App\Post::find("AVp_tCaAoV7YQD3Esfmp");
插入模型

要创建一个新的文档,只需创建一个新的模型实例,设置模型上的属性,然后调用save()方法

<?php
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
    /**
     * Create a new post instance.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // Validate the request...
        $post = new Post;
        $post->title = $request->title;
        $post->save();
    }
}
更新模型

save()方法也可以用来更新已存在的模型。要更新模型,您应该检索它,设置您想要更新的任何属性,然后调用保存方法。

$post = App\Post::find(1);
$post->title = 'New Post Title';
$post->save();
删除模型

要删除模型,请在模型实例上调用delete()方法

$post = App\Post::find(1);
$post->delete();
查询作用域

作用域允许您定义可以在整个应用程序中重复使用的常用约束集合。例如,您可能需要频繁检索所有被认为是“热门”的帖子。要定义一个作用域,只需在Eloquent模型方法前加上scope前缀。

作用域应始终返回一个查询实例。

<?php
namespace App;
use Omar\Laralestic\Model;
class Post extends Model
{
    /**
     * Scope a query to only include popular posts.
     *
     * @param \Omar\Laralestic\Query $query
     * @return \Omar\Laralestic\Query
     */
    public function scopePopular($query, $votes)
    {
        return $query->where('votes', '>', $votes);
    }
    /**
     * Scope a query to only include active posts.
     *
     * @param \Omar\Laralestic\Query $query
     * @return \Omar\Laralestic\Query
     */
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
}

作用域定义后,您可以在查询模型时调用作用域方法。但是,调用方法时不需要包含作用域前缀。您甚至可以链式调用各种作用域,例如

$posts = App\Post::popular(100)->active()->orderBy('created_at')->get();
访问器和修改器
定义访问器

要定义一个访问器,在您的模型上创建一个getFooAttribute方法,其中Foo是您希望访问的列的“studly”形式名称。在这个例子中,我们将定义一个访问器来处理title属性。访问器将被模型自动调用,当尝试检索title属性的值时

<?php
namespace App;
use Omar\Laralestic\Model;
class post extends Model
{
    /**
     * Get the post title.
     *
     * @param  string  $value
     * @return string
     */
    public function getTitleAttribute($value)
    {
        return ucfirst($value);
    }
}

如你所见,原始列的值被传递给访问器,这使得你可以操纵并返回该值。要访问访问器的值,你可以简单地在模型实例上访问title属性

$post = App\Post::find(1);
$title = $post->title;

偶尔,你可能需要添加没有在索引中对应字段的数组属性。为此,只需为值定义一个访问器

public function getIsPublishedAttribute()
{
    return $this->attributes['status'] == 1;
}

一旦创建了访问器,只需将其添加到模型上的appends属性中

protected $appends = ['is_published'];

一旦属性被添加到appends列表中,它就会包含在模型的数组中。

定义修改器

要定义一个修改器,在模型上定义一个setFooAttribute方法,其中Foo是要访问的列的“大驼峰”命名字符串。所以,再次定义一个title属性的修改器。这个修改器将在尝试设置模型上的title属性值时自动调用。

<?php
namespace App;
use Omar\Laralestic\Model;
class post extends Model
{
    /**
     * Set the post title.
     *
     * @param  string  $value
     * @return void
     */
    public function setTitleAttribute($value)
    {
        return strtolower($value);
    }
}

修改器将接收到要设置的属性值,允许您操纵该值并将操纵后的值设置在模型内部$attributes属性上。例如,如果我们尝试将标题属性设置为Awesome post to read

$post = App\Post::find(1);
$post->title = 'Awesome post to read';

在这个例子中,setTitleAttribute函数将使用Awesome post to read作为参数被调用。然后,修改器将对名称应用strtolower函数,并将结果值设置在内部的$attributes数组中。

属性类型转换

模型上的$casts属性提供了一个方便的方法来将属性转换为常见的数据类型。$casts属性应该是一个数组,其中键是要转换的属性名称,值是要转换的列的类型。支持的类型转换有:integerfloatdoublestringbooleanobjectarray

例如,让我们将存储在我们的索引中的整数(0或1)的is_published属性转换为boolean

<?php
namespace App;
use Omar\Laralestic\Model;
class Post extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'is_published' => 'boolean',
    ];
}

现在,当您访问is_published属性时,它总是会转换为boolean,即使底层的值在索引中以整数形式存储

$post = App\Post::find(1);
if ($post->is_published) {
    //
}

作为查询构建器的用法

创建新的索引

ES::create("my_index");
    
# or 
    
ES::index("my_index")->create();
使用自定义选项创建索引(可选)
ES::index("my_index")->create(function($index){
        
    $index->shards(5)->replicas(1)->mapping([
        'my_type' => [
            'properties' => [
                'first_name' => [
                    'type' => 'string',
                ],
                'age' => [
                    'type' => 'integer'
                ]
            ]
        ]
    ])
    
});
    
# or
    
ES::create("my_index", function($index){
  
      $index->shards(5)->replicas(1)->mapping([
          'my_type' => [
              'properties' => [
                  'first_name' => [
                      'type' => 'string',
                  ],
                  'age' => [
                      'type' => 'integer'
                  ]
              ]
          ]
      ])
  
});

删除索引

ES::drop("my_index");
    
# or
    
ES::index("my_index")->drop();

运行查询

$documents = ES::connection("default")
                ->index("my_index")
                ->type("my_type")
                ->get();    # return a collection of results

您可以将上述查询重写为

$documents = ES::type("my_type")->get();    # return a collection of results

查询构建器将使用默认连接,配置文件es.php中的索引名称。

查询中的连接和索引名称会覆盖配置文件es.php中的连接和索引名称。

通过id获取文档
ES::type("my_type")->id(3)->first();
    
# or
    
ES::type("my_type")->_id(3)->first();
排序
ES::type("my_type")->orderBy("created_at", "desc")->get();
    
# Sorting with text search score
    
ES::type("my_type")->orderBy("_score")->get();
限制和偏移量
ES::type("my_type")->take(10)->skip(5)->get();
仅选择特定字段
ES::type("my_type")->select("title", "content")->take(10)->skip(5)->get();
where子句
ES::type("my_type")->where("status", "published")->get();
# or
ES::type("my_type")->where("status", "=", "published")->get();
where大于
ES::type("my_type")->where("views", ">", 150)->get();
where大于等于
ES::type("my_type")->where("views", ">=", 150)->get();
where小于
ES::type("my_type")->where("views", "<", 150)->get();
where小于等于
ES::type("my_type")->where("views", "<=", 150)->get();
where模糊匹配
ES::type("my_type")->where("title", "like", "foo")->get();
where字段存在
ES::type("my_type")->where("hobbies", "exists", true)->get(); 
# or 
ES::type("my_type")->whereExists("hobbies", true)->get();
where in子句
ES::type("my_type")->whereIn("id", [100, 150])->get();
where between子句
ES::type("my_type")->whereBetween("id", 100, 150)->get();
# or 
ES::type("my_type")->whereBetween("id", [100, 150])->get();
where not子句
ES::type("my_type")->whereNot("status", "published")->get(); 
# or
ES::type("my_type")->whereNot("status", "=", "published")->get();
where not大于
ES::type("my_type")->whereNot("views", ">", 150)->get();
where not大于等于
ES::type("my_type")->whereNot("views", ">=", 150)->get();
where not小于
ES::type("my_type")->whereNot("views", "<", 150)->get();
where not小于等于
ES::type("my_type")->whereNot("views", "<=", 150)->get();
where not模糊匹配
ES::type("my_type")->whereNot("title", "like", "foo")->get();
where not字段存在
ES::type("my_type")->whereNot("hobbies", "exists", true)->get(); 
# or
ES::type("my_type")->whereExists("hobbies", true)->get();
where not in子句
ES::type("my_type")->whereNotIn("id", [100, 150])->get();
where not between子句
ES::type("my_type")->whereNotBetween("id", 100, 150)->get();
# or
ES::type("my_type")->whereNotBetween("id", [100, 150])->get();
根据地理点的距离搜索
ES::type("my_type")->distance("location", ["lat" => -33.8688197, "lon" => 151.20929550000005], "10km")->get();
# or
ES::type("my_type")->distance("location", "-33.8688197,151.20929550000005", "10km")->get();
# or
ES::type("my_type")->distance("location", [151.20929550000005, -33.8688197], "10km")->get();  
使用数组查询搜索
ES::type("my_type")->body([
    "query" => [
         "bool" => [
             "must" => [
                 [ "match" => [ "address" => "mill" ] ],
                 [ "match" => [ "address" => "lane" ] ]
             ]
         ]
     ]
])->get();
# Note that you can mix between query builder and array queries.
# The query builder will will be merged with the array query.
ES::type("my_type")->body([
	"_source" => ["content"]
	
	"query" => [
	     "bool" => [
	         "must" => [
	             [ "match" => [ "address" => "mill" ] ]
	         ]
	     ]
	],
	   
	"sort" => [
		"_score"
	]
     
])->select("name")->orderBy("created_at", "desc")->take(10)->skip(5)->get();
# The result query will be
/*
Array
(
    [index] => my_index
    [type] => my_type
    [body] => Array
        (
            [_source] => Array
                (
                    [0] => content
                    [1] => name
                )
            [query] => Array
                (
                    [bool] => Array
                        (
                            [must] => Array
                                (
                                    [0] => Array
                                        (
                                            [match] => Array
                                                (
                                                    [address] => mill
                                                )
                                        )
                                )
                        )
                )
            [sort] => Array
                (
                    [0] => _score
                    [1] => Array
                        (
                            [created_at] => desc
                        )
                )
        )
    [from] => 5
    [size] => 10
    [client] => Array
        (
            [ignore] => Array
                (
                )
        )
)
*/
搜索整个文档
ES::type("my_type")->search("hello")->get();
    
# search with Boost = 2
    
ES::type("my_type")->search("hello", 2)->get();
# search within specific fields with different weights
ES::type("my_type")->search("hello", function($search){
	$search->boost(2)->fields(["title" => 2, "content" => 1])
})->get();
使用高亮字段搜索
$doc = ES::type("my_type")->highlight("title")->search("hello")->first();
# Multiple fields Highlighting is allowed.
$doc = ES::type("my_type")->highlight("title", "content")->search("hello")->first();
# Return all highlights as array using $doc->getHighlights() method.
$doc->getHighlights();
# Also you can return only highlights of specific field.
$doc->getHighlights("title");
仅返回第一条记录
ES::type("my_type")->search("hello")->first();
仅返回计数
ES::type("my_type")->search("hello")->count();
Scan-and-Scroll查询
# These queries are suitable for large amount of data. 
# A scrolled search allows you to do an initial search and to keep pulling batches of results
# from Elasticsearch until there are no more results left.
# It’s a bit like a cursor in a traditional database
    
$documents = ES::type("my_type")->search("hello")
                 ->scroll("2m")
                 ->take(1000)
                 ->get();
# Response will contain a hashed code `scroll_id` will be used to get the next result by running
$documents = ES::type("my_type")->search("hello")
                 ->scroll("2m")
                 ->scrollID("DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAFMFlJQOEtTdnJIUklhcU1FX2VqS0EwZncAAAAAAAABSxZSUDhLU3ZySFJJYXFNRV9laktBMGZ3AAAAAAAAAU4WUlA4S1N2ckhSSWFxTUVfZWpLQTBmdwAAAAAAAAFPFlJQOEtTdnJIUklhcU1FX2VqS0EwZncAAAAAAAABTRZSUDhLU3ZySFJJYXFNRV9laktBMGZ3")
                 ->get();
# And so on ...
# Note that you don't need to write the query parameters in every scroll. All you need the `scroll_id` and query scroll time.
    
# To clear `scroll_id` 
  
ES::type("my_type")->scrollID("DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAFMFlJQOEtTdnJIUklhcU1FX2VqS0EwZncAAAAAAAABSxZSUDhLU3ZySFJJYXFNRV9laktBMGZ3AAAAAAAAAU4WUlA4S1N2ckhSSWFxTUVfZWpLQTBmdwAAAAAAAAFPFlJQOEtTdnJIUklhcU1FX2VqS0EwZncAAAAAAAABTRZSUDhLU3ZySFJJYXFNRV9laktBMGZ3")
        ->clear();
每页5条记录分页结果
$documents = ES::type("my_type")->search("hello")->paginate(5);
    
# Getting pagination links
    
$documents->links();
# Bootstrap 4 pagination
$documents->links("bootstrap-4");
# Simple bootstrap 4 pagination
$documents->links("simple-bootstrap-4");
# Simple pagination
$documents->links("simple-default");

这些都是您可能使用的分页方法

$documents->count()
$documents->currentPage()
$documents->firstItem()
$documents->hasMorePages()
$documents->lastItem()
$documents->lastPage()
$documents->nextPageUrl()
$documents->perPage()
$documents->previousPageUrl()
$documents->total()
$documents->url($page)
获取不执行的查询数组
ES::type("my_type")->search("hello")->where("views", ">", 150)->query();
获取原始Elasticsearch响应
ES::type("my_type")->search("hello")->where("views", ">", 150)->response();
忽略不良HTTP响应
ES::type("my_type")->ignore(404, 500)->id(5)->first();
查询缓存(Laravel & Lumen)

该软件包包含一个基于laravel cache的内置缓存层。

ES::type("my_type")->search("hello")->remember(10)->get();
	
# Specify a custom cache key
ES::type("my_type")->search("hello")->remember(10, "last_documents")->get();
	
# Caching using other available driver
	
ES::type("my_type")->search("hello")->cacheDriver("redis")->remember(10, "last_documents")->get();
	
# Caching with cache key prefix
	
ES::type("my_type")->search("hello")->cacheDriver("redis")->cachePrefix("docs")->remember(10, "last_documents")->get();
执行Elasticsearch原始查询
ES::raw()->search([
    "index" => "my_index",
    "type"  => "my_type",
    "body" => [
        "query" => [
            "bool" => [
                "must" => [
                    [ "match" => [ "address" => "mill" ] ],
                    [ "match" => [ "address" => "lane" ] ]
                ]
            ]
        ]
    ]
]);
插入新的文档
ES::type("my_type")->id(3)->insert([
    "title" => "Test document",
    "content" => "Sample content"
]);
     
# A new document will be inserted with _id = 3.
  
# [id is optional] if not specified, a unique hash key will be generated.
一次性批量插入多个文档。
# Main query
ES::index("my_index")->type("my_type")->bulk(function ($bulk){
    # Sub queries
	$bulk->index("my_index_1")->type("my_type_1")->id(10)->insert(["title" => "Test document 1","content" => "Sample content 1"]);
	$bulk->index("my_index_2")->id(11)->insert(["title" => "Test document 2","content" => "Sample content 2"]);
	$bulk->id(12)->insert(["title" => "Test document 3", "content" => "Sample content 3"]);
	
});
# Notes from the above query:
# As index and type names are required for insertion, Index and type names are extendable. This means that: 
# If index() is not specified in subquery:
# -- The builder will get index name from the main query.
# -- if index is not specified in main query, the builder will get index name from configuration file.
# And
# If type() is not specified in subquery:
# -- The builder will get type name from the main query.
# you can use old bulk code style using multidimensional array of [id => data] pairs
 
ES::type("my_type")->bulk([
 
	10 => [
		"title" => "Test document 1",
		"content" => "Sample content 1"
	],
	 
	11 => [
		"title" => "Test document 2",
		"content" => "Sample content 2"
	]
 
]);
 
# The two given documents will be inserted with its associated ids
更新现有文档
ES::type("my_type")->id(3)->update([
   "title" => "Test document",
   "content" => "sample content"
]);
    
# Document has _id = 3 will be updated.
    
# [id is required]
# Bulk update
ES::type("my_type")->bulk(function ($bulk){
    $bulk->id(10)->update(["title" => "Test document 1","content" => "Sample content 1"]);
    $bulk->id(11)->update(["title" => "Test document 2","content" => "Sample content 2"]);
});
增加字段
ES::type("my_type")->id(3)->increment("views");
    
# Document has _id = 3 will be incremented by 1.
    
ES::type("my_type")->id(3)->increment("views", 3);
    
# Document has _id = 3 will be incremented by 3.
# [id is required]
减少字段
ES::type("my_type")->id(3)->decrement("views");
    
# Document has _id = 3 will be decremented by 1.
    
ES::type("my_type")->id(3)->decrement("views", 3);
    
# Document has _id = 3 will be decremented by 3.
# [id is required]
使用脚本更新
# increment field by script
    
ES::type("my_type")->id(3)->script(
    "ctx._source.$field += params.count",
    ["count" => 1]
);
    
# add php tag to tags array list
    
ES::type("my_type")->id(3)->script(
    "ctx._source.tags.add(params.tag)",
    ["tag" => "php"]
);
    
# delete the doc if the tags field contain mongodb, otherwise it does nothing (noop)
    
ES::type("my_type")->id(3)->script(
    "if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'none' }",
    ["tag" => "mongodb"]
);
删除文档
ES::type("my_type")->id(3)->delete();
    
# Document has _id = 3 will be deleted.
    
# [id is required]
# Bulk delete
ES::type("my_type")->bulk(function ($bulk){
    $bulk->id(10)->delete();
    $bulk->id(11)->delete();
});

版本

变更日志

作者

El-Hendawy - omar.el.hendawy@outlook.com

错误、建议和贡献

请使用Github来报告错误、发表评论或提出建议。

许可证

MIT

祝您搜索愉快。