ratkor/laravel-crate.io

Crate.io 驱动程序用于 Laravel

v13.0.0 2023-10-24 07:45 UTC

README

这是对 Crate.io 的 Eloquent 和查询构建器的支持。通过扩展原始 Laravel API 和 Crate PDO 驱动程序来扩展。

Crate 和 Crate PDO

Crate 是一个基于 Elasticsearch、Lucene 和其他好东西的分布式 SQL 数据库。有关更多信息,请参阅他们的官方页面 Crate.io

Crate.io 发布了 PDODBAL 驱动程序,以便轻松访问 crate 数据库服务器。Laravel-crate.io 项目在连接到 Crate 数据库时使用这些适配器。

项目状态

!!!! 注意:版本 11 中有一个破坏性的更改。请参见下面的变更日志。

Laravel-crate.io 在我们的内部项目中使用。我们做了一大堆单元测试,驱动程序看起来不错。我们在数据库服务器前使用 id 作为缓存层。Crate 非常快(Elasticsearch)并且大大减轻了我们的数据库服务器负担。

如果你发现任何错误,请提交问题报告.

安装

支持 Laravel 5.5、6、7、8、9 和 10。

在 composer.json 中添加 require

    composer require ratkor/laravel-crate.io

注意

始终在 composer.json 中使用标记版本。laravel-crate.io 的最新(master)版本仅与最新 Laravel 兼容。最新 Laravel 在查询解析中有一系列不同的函数参数,如果你尝试使用 master 分支与较旧的 Laravel 兼容,你将得到解析错误。

Laravel 5.5+ 使用包自动发现,因此不需要手动添加 ServiceProvider。

当然,你必须安装 crate.io 服务器。请参阅他们的网站上的安装说明。

PHP

版本 12 支持 PHP 8.1。

版本 10.1 支持 PHP 8。
我们在 ubuntu 上使用 PHP 8.0、crate-dbal 3 和 phpunit 9.5 运行测试。所有测试都通过了。

标记为 9 和更高版本的版本需要 php 7.2.5

配置

打开 config/database.php 并添加新的 crate 数据库连接(使用与您的设置匹配的配置值)

'crate' => array(
    'driver'   => 'crate',
    'host'     => 'localhost',
    'database' => 'doc',
    'port'     => 4200,
),

接下来,将默认数据库连接更改为 "crate"

'default' => 'crate',

HTTP Basic Auth 配置

此驱动程序支持标准的 CrateDB 身份验证方法 trustpassword 通过 HTTP Basic Auth。要启用此功能,请编辑您在上一个步骤中创建的 crate 配置,并添加 usernamepassword 以及您系统中的相应值。

有关 CrateDB 身份验证方法的更多信息,请参阅 CrateDB 关于 身份验证方法 的文档。

'crate' => array(
    'driver'      => 'crate',
    'host'        => 'localhost',
    'database'    => 'doc',
    'port'        => 4200,
    'username'    => 'MyUsername',
    'password'    => 'MyPassword',
),

多主机配置

此驱动程序可以处理到多个 crate 主机的连接。要使用它们,请将 host 配置参数写入为逗号分隔的主机列表。例如

'crate' => array(
    'driver'   => 'crate',
    'host'     => 'localhost,10.0.0.1,10.0.0.2',
    'database' => 'doc',
    'port'     => 4200,
),

在这种情况下创建的 DSN 看起来像

'crate:localhost:4200,10.0.0.1:4200,10.0.0.2:4200'

如果您需要指定不同的端口,请将它们添加到 host 参数中,例如

    'host'     => 'localhost:4201,10.0.0.1:4300,10.0.0.2',

这将创建一个类似以下 DSN 的 DSN

'crate:localhost:4201,10.0.0.1:4300,10.0.0.2:4200'

随机化

crate-pdo 从主机列表中获取第一个主机。为了克服这一点,我们将所有主机随机化,以便连接到多个crate服务器得以分布。如果您不想随机化,请添加一个randomHosts参数并将其设置为false

'crate' => array(
    'driver'   => 'crate',
    'host'     => 'localhost,10.0.0.1,10.0.0.2',
    'database' => 'doc',
    'port'     => 4200,
    'randomHosts' => false,
),

哪些可行,哪些不可行

Crate.io支持许多SQL语句,但并非所有。如果您对此有疑问,请务必查看他们的网站

对于您可能错误尝试使用的语句,我们抛出了RatkoR\Crate\NotImplementedException。我们尽量覆盖了所有这些,但如果遗漏了任何,您将收到来自Crate DB的异常。

不支持的大功能包括

  • 连接
  • 子查询
  • 自增 - 您必须自己管理这些
  • whereBetween(s)
  • 唯一索引
  • 外键(和相关项)
  • 删除、重命名列(添加字段是可行的)
  • 列名如 _id、_version、_score - 这些是受限制的,crate在内部使用

添加了以下Crate特定功能

  • 对象类型
  • 数组类型
  • 索引关闭,索引纯文本
  • 无分析器的单字段或多字段全文索引
  • 表分区
  • 生成列

此外,Article::truncate()已被更改为静默使用delete from article;

注意,Crate.io不支持表或模式名称中的大写字母。有关此限制和其他限制,请参阅此处

模式支持

迁移和模式是支持的。您可以使用artisan migrate命令创建或删除表。

Crate只有字段类型的一个子集(和一些新类型),因此请选择合适的类型。

Crate类型

  • 布尔值
  • 字符串
  • 数字(整数、长整型、短整型、双精度浮点型、浮点型、字节)
  • ip、geo_point(仍需实现这两个类型)
  • 时间戳
  • 对象
  • 数组

某些SQL类型被静默链接到crate类型。例如,bigInteger链接到longtext、mediumtext、longtext、enum链接到string,……

迁移文件中模式的一个示例

        Schema::create('article', function(Blueprint $table)
        {
            $table->integer('id');

            $table->string('title')->index('plain');
            $table->mediumText('summary');
            $table->text('internal_Comment')->index('off');
            $table->text('body')->index('fulltext:english');
            $table->bigInteger('nb_views');
            $table->timestamp('published_on');

            $table->arrayField('images','object as (id integer, title string');
            $table->objectField('author','(dynamic) as (id integer, name string)');

            $table->timestamps();

            $table->primary('id');
        });

blob表

创建(和删除)blob表也是支持的。Blob表没有任意列,只有摘要和最后修改时间。甚至这些也是自动创建的。

创建blob模式的一个示例

    Schema::createBlob('myblob');

不需要回调参数(创建blob()的第二个参数,用于定义字段)。如果您传递它,它将被静默忽略。

要在模式中删除表,请

    Schema::dropBlob('myblob');

一些SQL/Crate模式差异的描述

单字段的全文索引可以添加为

$table->index('field1','fulltext');

$table->string('field1')->index('fulltext');

多字段的全文索引

$table->index(['field1','field2'],'fulltext');

多字段全文索引(使用英文分析器)

$table->index(['field1','field2'],'fulltext:english');

单字段的唯一键

$table->primary('field1');

多字段的唯一键

$table->primary(['f_id','f2_id']);

不包括字段在默认索引中

$table->string('not_important_field')->index('off');

一个PLAIN索引(默认索引)

$table->string('field')->index('plain');

$table->string('field')->index();

或者简单地将其省略,crate将对其进行索引。

在迁移脚本中删除表

Schema::drop('article');

要添加一个'对象'字段,请使用

$table->objectField('field_name', 'object parameters');

其中对象参数可以是crate接受的除对象之外的所有参数。请参阅它们的文档以了解对象。示例包括

$table->objectField('my_object_1','as (f_date timestamp)');
$table->objectField('my_object_2','(dynamic) as (name string, birthday timestamp)');

添加一个'数组'字段

数组可以通过->arrayField('name', '数组参数')进行添加。与object类型一样,数组参数可以包含crate允许数组中的任何属性。请参阅其文档。动态对象数组的示例

$table->arrayField('f_array','object as (age integer, name string');

基本用法

通过crate数据库连接,您可以进行简单的甚至更复杂的查询。一些示例包括

$articles = DB::select('select * from article where id = ?', array(1));

$user = DB::table('user')->where('email','some@example.com')->first();

$users = DB::table('user')->get();

Eloquent

要使用Eloquent,您需要使用Crate Eloquent模型。

use RatkoR\Crate\Eloquent\Model AS Eloquent;

class Article extends Eloquent {}

您可以使用(几乎)与原始eloquent模型相同的所有eloquent功能。

要使用不同的表名,请使用

protected $table = 'myArticles';

等等...

Eloquent模型别名

而不是在所有eloquent类中添加

use RatkoR\Crate\Eloquent\Model AS Eloquent;

您可以在config/app.php中的alias数组中添加别名

'CrateEloquent' => 'RatkoR\Crate\Eloquent\Model'

这将允许您将类定义缩短为

use CrateEloquent;
class Article extends CrateEloquent {}

Eloquent用法

它可以用作大多数情况下与原始Laravel eloquent模型相同。

获取所有文章
$articles = Article::all();
通过主键获取
$article = Article::find(1);
使用where(s)
$articles = Article::where('name','LIKE','Star%')->where('views','>',100)->get();
使用limits(s)
$articles = Article::where('name','LIKE','Star%')->take(10)->get();
使用whereIn
$articles = Article::whereIn('id',[1,2,3])->get();
使用select字段
$article = Article::select('id','name')->where('id',1)->first();
使用count
$nb = Article::where('views','>',100)->count();
复杂的where(s)
$articles = Article::where('id','=',3)->orWhere(function($query)
            {
                $query->where('title', 'Star Wars 7')
                      ->orWhere('title', 'none');
            })->get();

等等...

插入
$new = Article::create([
    'id' => 1, // don't forget, there is no auto increment
    'title' => 'John Doe and friends',
    'summary' => '...',
    'array_of_strings' => ['one', 'two'],
    'object_field' => ['author' => 'Someone', 'title' => 'Editpr']
]);
更新
$article = Article::find(1);

$article->title = 'Brand new title';
$article->array_of_strings = ['tree', 'four'];
$article->object_field = ['author' => 'Someone Else', 'title' => 'Administrator'];
$article->save();

注意:当您更新数组或对象字段时,该字段中的任何内容都将被您提供的替换。您不能仅追加或更改一个值。

$article->object_field = ['crated_by' => 'Third Person'];

将不会向已存在的字段追加'created_by'字段,而是在'object_field'中覆盖并仅留下'created_by'值。要修复此问题,请执行以下更新操作

$newValues = $article->object_field;
$newValues['created_by'] = 'Third Person';

$article->object_field = $newValues;
删除
$article = Article::find(1);
$article->delete();

变更日志

版本 13

支持laravel 10。

版本 12

支持laravel 9(感谢Julian Martin

版本 11

重大更改

版本11将获取方法从PDO::FETCH_ASSOC更改为Laravel的默认PDO::FETCH_OBJ

版本 10.1

添加了PHP 8支持。当在安装了PHP 8的机器上运行时,所有现有测试都通过。代码(只有composer.json进行了更新)不需要更改。

版本 10

将项目更新为与laravel 8兼容。

注意:crate-pdo现在允许将对象保存到字符串字段中。

如果您有一个具有name字段设置为字符串的User对象,并且您执行以下操作

$foo = new stdClass();
$foo->bar = 'test';
User::create(['id'=>1,'name'=> $foo]);

它将使用设置'nam'字段的'{"bar": "test"}'对象进行插入。我不知道这是功能还是错误...我将由开发人员决定是否使用它。

Connection::recordsHaveBeenModified()现在正确调用所有已定义了它的Laravel。

版本 9.1

支持表分区和生成表(pull #34)。已更新crate-dbal到版本2.0(pull #33)。

版本 9.0

感谢Julian Martin,该项目现在与laravel 6.X兼容。PHP 7.2现在是强制性的(对Laravel 6也是强制性的)。

版本 8.0

已更新项目以与laravel 5.8兼容。没有添加新功能,仅修复了与L 5.8更改的兼容性问题。

重新编写了测试用例以与phpunit 8和9兼容。

版本 7.0

已更新项目以与laravel 5.7兼容。没有添加新功能,仅修复了与L 5.7更改的兼容性问题。

版本 6.0

已更新项目以与laravel 5.6兼容

版本 5.0

已更新项目以与laravel 5.5兼容。新的5.0版本仅与laravel 5.5.X兼容。

版本 4.0

已更新并与laravel 5.4同步。5.4中的runQueryCallback方法与5.3不同。因此,您必须使用4.0与laravel 5.4一起使用。

这是一个内部更改,您的工作方式与之前使用laravel和crate相同。这只是通知您4.0与<5.3的laravels不兼容。

版本 3.1

异常

版本 3.1 带有自定义的 QueryException。这意味着在出现 SQL 错误的情况下,您将能够看到 SQL 以及它的参数,即使其中一些是对象或数组。

$foo = new stdClass();
$foo->bar = 'test';
User::create(['id'=>1,'name'=> $foo,'email'=>'user1@example.com']);

抛出

QueryException:
SQLActionException [Validation failed for name: cannot cast {bar=test} to string] (SQL: insert into users (id, name, email) values (1, {"bar":"test"}, "user1@example.com"))
连接

连接到 crate 时可以接受表前缀。将 prefix 键添加到您的 crate 配置中即可使用。

'crate' => array(
    'driver'   => 'crate',
    'host'     => 'localhost',
    'database' => 'doc',
    'port'     => 4200,
    'prefix'   => 'sys',
),
新类型
  • geoPoint
  • geoShape
  • ip

提交 和官方 crate 文档

测试

有两种测试类型

  • 词法测试
  • 数据测试

词法测试

词法测试检查由查询构建器生成的 SQL 语句是否在语义上正确。

这些测试执行相对较快。它们检查所有常见的 SQL 语句是否不受代码更改的影响。

数据测试

数据测试连接到实际的 Crate.io 服务器,并尝试在那里管理数据。选择、插入、更新、删除查询,所有这些都被测试。

这些测试需要更长的时间才能完成。我们发现,在插入记录后立即查询该记录可能会产生负面结果。Crate 需要在插入(或删除、或更新)请求和所有后续的查询此更改的选择之间留出一些时间。因此,我们在测试代码中有几个 sleep(1) 语句。

首次运行数据测试可能会失败,因为此时 migration 表可能还不存在。尝试重新运行测试,它将顺利进行。哦,您还必须在 DatabaseMigrationRepository::createRepository 中的 $table->increment('id') 更改为 $table->integer('id');,否则它将损坏,因为增量不支持。

测试的连接属性在 tests/DataTests/Config/database.php 文件中,并且可以根据您的设置进行更改。

数据测试将创建

  • 用于测试表迁移的 t_migration 表,
  • 用于一些示例用户数据的 t_users 表。