ov-code / elasticoc
Elastic 的面向对象客户端。不再有无穷无尽的数组,无法控制。不再有额外的字段,不再有日期字符串。现在 Elastic 将按预期工作。
Requires
- php: ^5.6 || ^7.0
- doctrine/annotations: 1.7.0
- elasticsearch/elasticsearch: ^7.0
This package is not auto-updated.
Last update: 2024-09-26 14:14:36 UTC
README
安装
composer require ov-code/elasticoc
功能
- 对象注解系统。不再需要无限的方法来检查是否是有效的 Elasticsearch 对象
- ElasticsearchClient 管理器。您不需要创建主机或任何东西,只需让 ElasticOc 为您完成这项工作即可
- 类似于 Laravel 的 Get|Search 函数。只需一行代码即可获取通过过滤器的所有对象,不再需要 while 循环、for 循环和 Elastic Scrolls
- 更容易制作时序数据,只需将索引中的问号(?)放在需要替换的部分即可。
待办事项
- 支持索引中的多个 TemplateValues
- 对象使聚合更容易阅读
- QueryBuilder
- 复杂字段
- 更好的缓存
ElasticOc
Elasticsearch 官方客户端并不差...相信我,我用 Elastic 和 curl 使用了一整年。但是,它有一个问题...嗯...这是 PHP 的问题,您永远不会知道每个变量的类型。除此之外,您总是会忘记在某个数组中过滤某些键,这将使对象变得混乱。
因此,您可以在数组中设置两千个过滤器,创建函数将所有这些白天时间转换为良好的格式等,或者您可以直接安装 ElasticOc 并忘记这一切。
如何使用它
准备对象
首先,让我们创建一个将作为我们对象的类。让我们称它为 Product。我们导入所需的两个类,即注解和 EsEntityV2,这将把我们的对象转换为 ElasticOc 对象。除此之外,我们还将添加两个最重要的部分注解,EsIndex 和 EsPrimaryKey
<?php
namespace App;
use ElasticSearchOC\Entities\EsEntityV2;
use ElasticSearchOC\Annotations as ElasticAnnotations;
/**
* @ElasticAnnotations\EsIndex("products-Index")
* @ElasticAnnotations\EsPrimaryKey('productId')
*/
class Product extends EsEntityV2{}
好的,这将是我们对象的“头部”,这将告诉索引是什么,在哪里,以及用于 Elasticsearch 中的 _uid 的属性。
EsIndex
这是最重要的注解,我们将使用它来配置主机设置和对象所在索引。如果您需要多个主机,可以使用多个此类注解。
此注解的属性如下
- 索引*
- 模板字段
- 时间格式
- URL
- 端口
- 协议
- 用户
- 密码
- sslVerification
索引、模板字段和时间格式
这很简单,是对象将保存到的索引...是的,这是 Elastic,那么您如何在时序中保存?简单,您将问号(?)放在需要替换的部分,您需要设置模板字段属性以将此 ? 替换为合适的字符串。
所以,想象一下,如果我们想要为每个制造商创建一个索引,这将是一段代码
/**
@ElasticAnnotations\EsIndex("product-index-?",templateField="manufacturer")
*/
但是,但是,因为总是有但是,想象一下,如果我们保存一个名为 Jacobs 的制造商的产品,然后将其更改为 Maliwan,如果您像那样保存对象,您将最终得到一个副本,一个在 Jacobs,一个在 Maliwan。目前 ElasticOc 不自动删除第一个。
如果您使用 EsFieldDate 作为模板字段,默认情况下,它将将其转换为 Ym 的 dateFormat,如果您想使用自定义的,请设置时间格式属性
/**
@ElasticAnnotations\EsIndex("product-index-?",templateField="created",timeFormat='Y-m-d')
*/
URL、协议和其他重要部分
默认情况下,索引将指向 localhost:9200 使用 http。您可以通过设置这些环境变量来更改默认参数
- ES_PROTOCOL
- ES_URL
- ES_PORT
- ES_USER
- ES_PASSWORD
如果您需要两个主机?没问题,您可以在注解中设置环境变量来使用,甚至如果您想的话,可以硬编码这些值...但当然,这不是一个好的实践。
/**
* @ElasticAnnotations\EsIndex("product-index", protocol='ES_PROTOCOL_2', url='ES_URL_2', port='ES_PORT_2', user='root', pass='please_dont_do_this')
*/
sslVerification
如果您与Elastic合作过一段时间,您就知道将SSL证书放入Elastic是一件多么痛苦的事情。如果出于某种原因您想禁用证书检查,将此属性设置为false,默认为true。
EsPrimaryKey
这个注解用于生成对象的_uid。如果您不使用此注解,您创建的每个对象都将被设置为PHP的唯一ID,以ID开头。
此注解的属性如下
- 属性*
- md5
这个注解不需要太多配置,您可以放置一个属性
/**
@ElasticAnnotations\EsPrimaryKey("productId")
*/
或者属性数组
/**
@ElasticAnnotations\EsPrimaryKey({"productId","manufacturer"})
*/
属性md5是一个布尔值,如果设置为true,则主键将转换为MD5,这对于具有多个主键的对象来说非常完美。
EsFieldBasic
让我们继续,我们将创建三个属性:productID,它将是我们的主键,name和Price。
/**
* @ElasticAnnotations\EsFieldBasic("productId", dataType="integer")
*/
public $productId;
/**
* @ElasticAnnotations\EsFieldBasic("name", dataType="string")
*/
public $name;
/**
* @ElasticAnnotations\EsFieldBasic("price", dataType="float",decimals="2")
*/
public $price;
我们需要创建所有属性的Get和Set,或者使它们成为公共的。第一个值是Elasticsearch中属性的名称,它可以与PHP中的名称不同,dataType是属性的类型。
此注解的属性如下
- 属性名称*
- canNull
- canArray
- default
- dataTipe*
- decimals*(如果dataType是Float或NoDecimal)
DataType
- String
- Integer
- Float
- Bool
- NoDecimal
NoDecimal 类型
如果您使用Elastic一段时间,您就知道自动类型可以有多糟糕。所以,为什么要与之抗争呢?NoDecimal会将任何乘以10的N次方的十进制数字保存(N是十进制位数)。所以如果您的数字是2.25,在Elastic中将是225。这将避免许多与索引类型相关的错误。
CanNull
Elastic可能没有主键、唯一字段...或者类似的东西,但至少现在,如果代码尝试将null放入不应该的地方,我们可以有一个错误。使用属性canNull来避免将重要字段设置为null。
/**
* @ElasticAnnotations\EsFieldBasic("price", dataType="float",decimals="2", canNull=false)
*/
默认值
有时0比任何数字都重要...但与0和非空值一起工作非常烦人,所以使用属性default,如果该变量将作为null进入Elastic,ElasticOc将为您设置它。
/**
* @ElasticAnnotations\EsFieldBasic("price", dataType="float",decimals="2",default=0)
*/
数组与CanArray
也许您的产品有多个价格,例如,实际价格和目录价格,您不想为此创建两个属性。没问题,ElasticOc会将所有属性转换,保留原始键。(目前它将所有字段转换为相同的类型)。
但也许您讨厌数组,ElasticOc为您提供了支持。将属性canArray设置为false,这样当属性变成数组时,在尝试保存对象时将崩溃。
/**
* @ElasticAnnotations\EsFieldBasic("price", dataType="float",decimals="2", canArray=false)
*/
EsFieldDate
让我们为Product对象添加一个日期,比如过期日期。
/**
* @ElasticAnnotations\EsFieldDate("expiry")
*/
public $expiry;
如您所见,这非常简单。您可以使用字符串或DateTime,但ElasticOc将在保存之前将此属性转换为DateTime,仅用于应用日期格式,所以如果您使用字符串,请小心格式。
此注解的属性如下
- 属性名称*
- canNull
- canArray
- default
- saveFormat
SaveFormat
默认格式将是Atom格式,Y-m-d\TH:i :sP,为什么?因为Elastic会自动将其映射到日期,所以您不需要自己创建索引。但当然,您可以使用saveFormat设置您喜欢的格式。
/**
* @ElasticAnnotations\EsFieldDate("expiry", saveFormat='y-m-d')
*/
public $expiry;
保存对象
因此,我们已创建我们的产品对象,在这个例子中,它将具有,ProductId作为主键,以及ProductId、Manufacturer和Price属性。所以如果您想保存它,就像一行代码那么简单。
$product = new Product();
$product->productId = 1;
$product->manufacturer = 'Jacobs';
$product->price = 2.25;
$product->save();
可能您需要保存数千个对象...当然,您不想做数千次调用,Elastic功能强大,但不能创造奇迹。因此,我们创建了bulk。
Product::beginBulk();
while($count<100){
$product = new Product();
$product->productId = $count;
$product->price = $count*$count;
$product->manufacturer = 'Jacobs';
$product->save();
$count++;
}
Product::commitBulk();
如果您不想创建一个已创建的对象,只需将函数save更改为update。
Product::beginBulk();
foreach($products as $product){
$product->productId = $count;
$product->price = $count*$count;
$product->manufacturer = 'Jacobs';
$product->update();
}
Product::commitBulk();
获取对象
对于检索,您有4个不同的函数
- get
- 分页
- 搜索
获取
这是一个简单的操作,当您只想获取一个对象或少量集合时使用。默认的使用方法很简单,只需将_uid作为参数传递。
$product = Product::get(1);
好的,如果您想获取两个产品呢?使用一个数组
$product = Product::get([1,2]);
是的,这可能很有用,但您想传递一个过滤器怎么办?也许您想获取一个制造商的所有对象,ElasticOc可以为您提供覆盖。
$product = Product::get(['manufacturer'=>'Jacobs'])
多个字段进行过滤?当然可以
$product = Product::get(['manufacturer'=>'Jacobs','price'=>2.25]);
分页
get是一个好函数,但您可能不想在同一个查询中获取所有对象,您在想。为此,我们有了分页函数。
//FIRST PAGE
$res = Products::paginate(['manufacturer'=>'Jacobs'], 20);
$products = $res->getObjects();
$search_after = $res->getSearch_After();
//SECOND PAGE
$res = Products::paginate(['manufacturer'=>'Jacobs'], 20,$search_after;
$products_second = $res->getObjects();
很简单,但等等,它不像Get函数,它不返回对象。它返回自定义对象EsResponse。这个对象不过是ElasticSearch的响应,但已转换为正确的格式,并添加了一些特殊功能。
例如,getSearch_After()函数会返回一个数组,您可以将它再次传递给分页函数,用于下一页。
搜索
这是一个重要的函数,当您想要原始的ElasticPower时,将查询传递给搜索,它将返回一个EsResponse。
$query = [
"size" => 20,
"query" => [
"term" => [
"manufacturer" => 'Jacobs'
]
]
];
$res = Products::search($query);
选项
在这3个函数中,最后一个参数始终是作为数组的Options,如果您有Elasticsearch选项查询,请将其放在这里,除此之外,它还接受一些自定义选项。
- custom-index:如果您只想在特定索引中搜索,当然您可以使用正常Elastic规则连接两个或多个索引。
- custom-index-values:如果您在具有TemplateField的索引中搜索对象,可以使用此选项传递值,例如,如果您想在具有TemplateField的Index中进行搜索,并且它有一个DateTime,我可以传递所有我想要搜索的DateTime。
- force-exists:如果Elastic在您正在搜索的索引不存在时抛出错误,ElasticOc通过在每个索引末尾添加一个星号(*)来修复此问题。如果您不希望这样做,而是希望抛出错误,请将force-exists设置为TRUE。
删除
删除函数的工作方式与get函数完全一样,实际上,它与get几乎相同。
Products::delete('2') //Will delete the object with id 2
Products::delete(['manufacturer'=>'Jacobs']) //Will delete all the objects with the manufacturer jacobs
如果您有要删除的对象在内存中,您始终可以调用函数deleteThis。
$product->deleteThis();
刷新
如果您进行了一些更改并需要立即对该索引进行查询,请调用函数Refresh,以便索引使更改可用。
$product->deleteThis();
Product::refresh();
Product::get($id);