emsifa/laci

PHP JSON 平面文件数据库管理系统

v0.3.0 2018-06-01 15:57 UTC

This package is auto-updated.

Last update: 2024-09-22 00:56:13 UTC


README

Build Status License

概述

LaciDB 是一个以 JSON 格式存储的平面文件数据库管理系统。由于 JSON 格式,LaciDB 类似于其他 NoSQL 数据库,具有无模式(schemaless)的特性。一个记录可以有不同的列。

在 LaciDB 中没有表的概念,而是集合(collection)。LaciDB 中的集合代表一个存储许多记录(格式为 JSON)的文件。

“Laci”这个名字来源于其功能和流程类似于桌面的抽屉。抽屉通常不需要钥匙(认证),只需打开 > 拿东西或 > 放东西 > 关上。在 LaciDB 中也是如此,每个查询都会打开文件 > 执行查询(select|insert|update|delete) > 关闭文件。Laci 也像我们知道的,是用来存放小物品的地方。不是像仓库或柜子那样的大件物品。

因此,LaciDB 适用于

  • 存储大量数据的数据库。
  • 需要高安全级别的数据库。

LaciDB 是为以下用途而设计的

  • 处理小的数据,如设置或其他小数据。
  • 为需要易于导入/导出和备份的便携式数据库。
  • 为需要易于自行编辑的数据库,无需使用专用软件。记事本也可以。

工作原理

LaciDB 的工作原理基本上是将 json_decode 的结果流过一系列“管道”,这些管道用于 过滤映射排序限制,最终执行以获取值、更改值或删除值。

以下是对其过程的说明

过滤

要执行过滤,您可以使用 where 和 orWhere 方法。这两个方法可以接受 Closure 参数或 key、operator、value 参数。

映射

映射用于在已过滤的每个记录上形成新值。

以下是一些映射记录的方法

map(Closure $mapper)

用于对已过滤的集合进行映射。

select(array $columns)

用于仅映射记录的某些列。

withOne(Collection|Query $relation, $key, $otherKey, $operator, $thisKey)

用于获取 1:1 关系。

withMany(Collection|Query $relation, $key, $otherKey, $operator, $thisKey)

用于获取 1:n 关系。

排序

排序用于对已过滤和映射的数据进行排序。要进行排序,您可以使用 sortBy($key, $ascending) 方法。参数 $key 可以是字符串 key/列,用于排序,或者 Closure,用于根据预先计算出的值进行排序。

限制/取值

在数据过滤、映射和排序完成后,您可以使用 skip($offset) 或 take($limit, $offset) 方法剪切和获取部分数据。

执行

在过滤、映射、排序和剪切后,下一步是执行结果。

以下是一些执行方法

get(array $columns = null)

获取集合中的记录集合。如果需要获取特定列,请在 $columns 数组中定义列。

first(array $columns = null)

获取集合中的一个(或多个)记录。如果需要获取特定列,请在 $columns 数组中定义列。

count()

获取集合中的数据量。

sum($key)

获取集合中特定键的总和。

avg($key)

从集合中获取特定键的平均值。

min($key)

从集合中的特定键获取最小值。

max($key)

从集合中的特定键获取最大值。

lists($key, $resultKey = null)

将集合中的特定键收集到数组中。

insert(array $data)

将新数据插入集合。

inserts(array $listData)

一次性将多个新数据插入集合。注意:在过滤或映射查询后,不能使用insert和inserts。

update(array $newData)

更新集合中经过过滤和映射的记录的数据。

save()

与update相同。只是save会根据映射结果保存记录,而不是像update那样根据$newData。

delete()

删除集合中经过过滤和映射的数据。

truncate()

删除所有数据。不需要事先进行过滤和映射。

示例

初始化

use Emsifa\Laci\Collection;

require 'vendor/autoload.php';

$collection = new Collection(__DIR__.'/users.json');

插入数据

$user = $collection->insert([
    'name' => 'John Doe',
    'email' => 'johndoe@mail.com',
    'password' => password_hash('password', PASSWORD_BCRYPT)
]);

$user将是一个如下所示的数组

[
    '_id' => '58745c13ad585',
    'name' => 'John Doe',
    'email' => 'johndoe@mail.com',
    'password' => '$2y$10$eMF03850wE6uII7UeujyjOU5Q2XLWz0QEZ1A9yiKPjbo3sA4qYh1m'
]

'_id'是uniqid()

通过ID查找单个记录

$user = $collection->find('58745c13ad585');

查找单个

$user = $collection->where('email', 'johndoe@mail.com')->first();

选择所有

$data = $collection->all();

更新

$collection->where('email', 'johndoe@mail.com')->update([
    'name' => 'John',
    'sex' => 'male'
]);

返回受影响记录的计数

删除

$collection->where('email', 'johndoe@mail.com')->delete();

返回受影响记录的计数

多次插入

$bookCollection = new Collection('db/books.json');

$bookCollection->inserts([
    [
        'title' => 'Foobar',
        'published_at' => '2016-02-23',
        'author' => [
            'name' => 'John Doe',
            'email' => 'johndoe@mail.com'
        ],
        'star' => 3,
        'views' => 100
    ],
    [
        'title' => 'Bazqux',
        'published_at' => '2014-01-10',
        'author' => [
            'name' => 'Jane Doe',
            'email' => 'janedoe@mail.com'
        ],
        'star' => 5,
        'views' => 56
    ],
    [
        'title' => 'Lorem Ipsum',
        'published_at' => '2013-05-12',
        'author' => [
            'name' => 'Jane Doe',
            'email' => 'janedoe@mail.com'
        ],
        'star' => 4,
        'views' => 96
    ],
]);

查找条件

// select * from books.json where author[name] = 'Jane Doe'
$bookCollection->where('author.name', 'Jane Doe')->get();

// select * from books.json where star > 3
$bookCollection->where('star', '>', 3)->get();

// select * from books.json where star > 3 AND author[name] = 'Jane Doe'
$bookCollection->where('star', '>', 3)->where('author.name', 'Jane Doe')->get();

// select * from books.json where star > 3 OR author[name] = 'Jane Doe'
$bookCollection->where('star', '>', 3)->orWhere('author.name', 'Jane Doe')->get();

// select * from books.json where (star > 3 OR author[name] = 'Jane Doe')
$bookCollection->where(function($book) {
    return $book['star'] > 3 OR $book['author.name'] == 'Jane Doe';
})->get();

操作符可以是'=', '<', '<=', '>', '>=', 'in', 'not in', 'between', 'match'。

获取特定列/键

// select author, title from books.json where star > 3
$bookCollection->where('star', '>', 3)->get(['author.name', 'title']);

列/键别名

// select author[name] as author_name, title from books.json where star > 3
$bookCollection->where('star', '>', 3)->get(['author.name:author_name', 'title']);

映射

$bookCollection->map(function($row) {
    $row['score'] = $row['star'] + $row['views'];
    return $row;
})
->sortBy('score', 'desc')
->get();

排序

// select * from books.json order by star asc
$bookCollection->sortBy('star')->get();

// select * from books.json order by star desc
$bookCollection->sortBy('star', 'desc')->get();

// sorting calculated value
$bookCollection->sortBy(function($row) {
    return $row['star'] + $row['views'];
}, 'desc')->get();

限制与偏移量

// select * from books.json offset 4
$bookCollection->skip(4)->get();

// select * from books.json limit 10 offset 4
$bookCollection->take(10, 4)->get();

连接

$userCollection = new Collection('db/users.json');
$bookCollection = new Collection('db/books.json');

// get user with 'books'
$userCollection->withMany($bookCollection, 'books', 'author.email', '=', 'email')->get();

// get books with 'user'
$bookCollection->withOne($userCollection, 'user', 'email', '=', 'author.email')->get();

映射与保存

$bookCollection->where('star', '>', 3)->map(function($row) {
    $row['star'] = $row['star'] += 2;
    return $row;
})->save();

事务

$bookCollection->begin();

try {

    // insert, update, delete, etc 
    // will stored into variable (memory)

    $bookCollection->commit(); // until this

} catch(Exception $e) {

    $bookCollection->rollback();

}

宏查询

宏查询允许我们向Emsifa\Laci\Collection的实例中添加新方法,以便可以更流畅地重复使用。

例如,如果我们想获取活跃用户的数据,如果使用常规方法,我们可以进行如下查询

$users->where('active', 1)->get();

如果上述方法被重复使用,有时我们可能会忘记识别活跃用户的值是1,或true,或'yes',或'YES',或'yes',或'y',或'Y',或'Ya',或'ya'等?

因此,为了简化操作,我们可以使用如下宏

$users->macro('active', function ($query) {
    return $query->where('active', 1);
});

因此,我们可以这样获取活跃用户

$users->active()->get();

这样不是更实用吗?