ov-code/elasticoc

Elastic 的面向对象客户端。不再有无穷无尽的数组,无法控制。不再有额外的字段,不再有日期字符串。现在 Elastic 将按预期工作。

1.6 2020-02-07 10:05 UTC

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);