[rakibtg/sleekdb]纯 PHP 实现的零依赖 NoSQL 扁平文件数据库

2026-05-02 奥古斯宏

写个小工具、做个内部系统,数据量不大但总得存点什么。开个 MySQL 觉得太重,用 SQLite 又不想写 SQL。SleekDB 就是给这种场景准备的:一个 PHP 文件就能搞定所有 CRUD,数据直接存成 JSON。

SleekDB 官网首页

安装

composer require rakibtg/sleekdb

要求 PHP >= 8.4(PHP 7.x 用 v2.15),需要 ext-json 和 ext-mbstring,基本是标配。

SleekDB Packagist 页面,累计安装 11.9 万次

基本使用

SleekDB 的核心概念是 Store(存储),相当于 MySQL 的表或 MongoDB 的集合。每个 Store 就是一个目录,里面的每条数据是一个 JSON 文件。

use SleekDB\Store;

// 数据存储目录(自动创建)
$dataDir = __DIR__ . '/database';

// 创建一个 Store(类似建表)
$users = new Store('users', $dataDir);

// 插入数据(返回的数据会带上自动生成的 _id)
$user = $users->insert([
    'name'   => 'augushong',
    'email'  => 'augushong@example.com',
    'role'   => 'admin',
]);
// $user['_id'] => 1

// 查询全部
$allUsers = $users->findAll();

就这么简单。没有连接字符串、没有迁移脚本、没有 ORM 配置。插入的是数组,查出来的也是数组。

SleekDB 完整功能演示

版权声明:本文由phpreturn.com(PHP武器库官网)原创和首发,所有权利归phpreturn(PHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

条件查询

SleekDB 通过链式查询构建器实现条件过滤,注意条件以数组形式传入:

use SleekDB\Store;

$articles = new Store('articles', $dataDir);

// 基础条件查询:where 接收 [字段, 操作符, 值] 数组
$results = $articles->createQueryBuilder()
    ->where(['status', '=', 'published'])
    ->getQuery()
    ->fetch();

// 多条件 AND(链式调用 where)
$results = $articles->createQueryBuilder()
    ->where(['category', '=', 'php'])
    ->where(['status', '=', 'published'])
    ->where(['views', '>', 100])
    ->getQuery()
    ->fetch();

// OR 条件
$results = $articles->createQueryBuilder()
    ->where(['category', '=', 'php'])
    ->orWhere(['category', '=', 'javascript'])
    ->getQuery()
    ->fetch();

// IN / NOT IN
$results = $articles->createQueryBuilder()
    ->in('id', [1, 3, 5, 7])
    ->getQuery()
    ->fetch();

// 排序 + 分页
$results = $articles->createQueryBuilder()
    ->where(['status', '=', 'published'])
    ->orderBy(['created_at' => 'desc'])
    ->limit(10)
    ->skip(0)
    ->getQuery()
    ->fetch();

嵌套属性查询

这是 SleekDB 的亮点之一。因为是无模式的文档数据库,数据可以任意嵌套,查询时用点号路径就能深入到嵌套字段:

// 插入带嵌套结构的数据
$articles->insert([
    'title'   => 'SleekDB 入门',
    'author'  => [
        'name' => 'augushong',
        'role' => 'admin'
    ],
    'tags'    => ['php', 'nosql', 'database'],
]);

// 直接按嵌套字段查询(点号路径)
$results = $articles->createQueryBuilder()
    ->where(['author.role', '=', 'admin'])     // 查 author.role === admin
    ->getQuery()
    ->fetch();

// 数组内元素匹配(contains 操作符)
$results = $articles->createQueryBuilder()
    ->where(['tags', 'contains', 'php'])       // tags 数组中包含 php
    ->getQuery()
    ->fetch();

不需要 JOIN,不需要关联表,数据怎么存的就怎么查。

模糊搜索和文本匹配

// LIKE 模糊匹配(支持 % 和 _ 通配符)
$results = $articles->createQueryBuilder()
    ->where(['title', 'like', '%PHP%'])
    ->getQuery()
    ->fetch();

// 全文搜索(指定搜索字段和关键词)
$results = $articles->search(['title', 'content'], 'SleekDB 教程');

// BETWEEN 范围查询
$results = $articles->createQueryBuilder()
    ->where(['views', 'between', [100, 1000]])
    ->getQuery()
    ->fetch();

更新和删除

// 按 ID 更新(返回更新后的完整数据)
$updated = $articles->updateById($articleId, [
    'title'   => '新标题',
    'status'  => 'published',
]);

// 批量更新:把所有草稿标记为归档
$count = $articles->createQueryBuilder()
    ->where(['status', '=', 'draft'])
    ->getQuery()
    ->update(['status' => 'archived']);

// 按 ID 删除
$articles->deleteById($articleId);

// 条件删除:删除所有浏览量为 0 的文章
$articles->createQueryBuilder()
    ->where(['views', '=', 0])
    ->getQuery()
    ->delete();

// 查找单条记录(按条件取第一条)
$firstAdmin = $users->findOneBy(['role', '=', 'admin']);

投影和去重

// 只选取指定字段(减少传输量)
$results = $articles->createQueryBuilder()
    ->select(['title', 'author.name', 'created_at'])
    ->getQuery()
    ->fetch();

// 排除某些字段(比如排除大段正文内容)
$results = $articles->createQueryBuilder()
    ->except(['content', 'raw_html'])
    ->getQuery()
    ->fetch();

// 字段去重
$categories = $articles->createQueryBuilder()
    ->distinct('category')
    ->getQuery()
    ->fetch();

// 统计数量
$count = count($articles->createQueryBuilder()
    ->where(['status', '=', 'published'])
    ->getQuery()
    ->fetch());

缓存机制

SleekDB 默认开启自动缓存。每次查询结果会被缓存到文件,后续相同查询直接读缓存文件,不再遍历所有 JSON 数据:

// 默认行为:自动缓存,insert/update/delete 时自动失效
$results = $articles->findAll(); // 第一次遍历文件,之后走缓存

// 手动控制缓存
$results = $articles->createQueryBuilder()
    ->disableCache()              // 本次查询不使用缓存
    ->getQuery()
    ->fetch();

$results = $articles->createQueryBuilder()
    ->useCache(3600)              // 缓存 1 小时
    ->getQuery()
    ->fetch();

$results = $articles->createQueryBuilder()
    ->regenerateCache()           // 强制刷新缓存
    ->getQuery()
    ->fetch();

初始化 Store 时也可以全局配置缓存策略:

$config = [
    'auto_cache'      => true,       // 是否启用自动缓存(默认 true)
    'cache_lifetime'  => null,       // 缓存有效期(秒),null 表示永不过期
    'primary_key'     => '_id',      // 主键字段名
];

$articles = new Store('articles', $dataDir, $config);

数据存储结构

看一下 SleekDB 实际在磁盘上存了什么:

版权声明:本文由phpreturn.com(PHP武器库官网)原创和首发,所有权利归phpreturn(PHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

database/
├── users/                  # 一个 Store 就是一个目录
│   ├── data/               # 每条记录一个 JSON 文件
│   │   ├── 1.json          # _id 为 1 的用户
│   │   ├── 2.json
│   │   └── 3.json
│   ├── cache/              # 查询缓存文件
│   │   └── abc123.no_lifetime.json
│   └── _cnt.sdb            # 自增计数器
└── articles/
    ├── data/
    │   └── 1.json
    └── cache/
        └── def456.json

每条记录就是一个独立的 JSON 文件,人类可读、随时可以备份迁移。

SleekDB 磁盘存储结构

适用场景和不适用场景

SleekDB 适合:

  • 个人博客、小型 CMS、后台管理工具
  • 不想配置数据库服务的环境(共享主机、Docker 容器内轻应用)
  • 原型开发和快速验证想法
  • 几 GB 以内的数据量,读写频率中等以下

不适合:

  • 高并发写入场景(没有事务支持,并发写入可能冲突)
  • 需要复杂关系查询的系统(没有 JOIN,虽然能模拟但不优雅)
  • 数据量超过几 GB 的场景(全量扫描性能下降明显)
  • 需要强一致性和事务保证的业务

如果你需要一个"比数组持久化、比 MySQL 轻得多"的方案,SleekDB 就是答案。

最近浏览
IP用户:43.139.*.*
44 分钟前 WeChat Android 6.0
IP用户:66.249.*.*
2 小时前 Googlebot
IP用户:66.249.*.*
3 小时前 Googlebot
IP用户:106.13.*.*
3 小时前 Chrome Mac 10.11
IP用户:106.13.*.*
3 小时前 Chrome Mac 10.11
IP用户:39.84.*.*
3 小时前 Firefox Windows 10
累计浏览次数:11
评论
点击登录
phpreturn,PHP武器库,专注PHP领域的项目和资讯,收录和介绍PHP相关项目。
最近浏览 点击登录
累计浏览次数:321314
一周浏览次数:2046
今日浏览次数:3

本站所有权利归 phpreturn.com 所有

举报/反馈/投稿邮箱:phpreturn@ulthon.com

鲁ICP备19027671号-2