survos/pixie-bundle

Symfony 扩展包,允许轻松实现 SQLite 键值查找

资助包维护!
kbond

安装: 258

依赖项: 0

建议者: 0

安全性: 0

星标: 0

关注者: 3

分支: 0

开放问题: 3

类型:symfony-bundle

1.5.340 2024-09-24 13:44 UTC

README

一个利用 Sqlite 创建索引型无 SQL 数据存储的 Symfony 扩展包。

灵感来源于 https://gist.github.com/sbrl/c3bfbbbb3d1419332e9ece1bac8bb71chttps://dexie.org/ 以及 Symfony PDO 缓存组件。

其核心思想是存储可以通过键或过滤器访问的字符串或非结构化数据。

最初,它只是一个字符串查找,可以是 JSON 字符串,例如通过 QID 查找 wikidata 对象,或者通过 imdb_id 在 csv 文件中查找电影。

您可以通过添加包含重命名字段和数据处理的指令的 .conf 文件来自定义导入过程。您还可以在导入和导出过程中监听事件。

Pixie 可以(最终将)使用 json schema 文件来定义字段。使用 LiFormBundle 并参考 https://json-schema.fullstack.org.cn/

索引可以通过命令行、监听器或 .conf 文件定义。有一种简洁的格式,是逗号分隔的字符串,还有详细的格式,是一个哈希,其中索引细节作为键。

如果安装了 api-platform,将有一个 API 端点。

与 survos/translation-bundle 集成

要将目录中的 csv 文件集合导入 Pixie 数据库,我们需要执行以下操作

  • 每个 csv 文件成为一个表,我们通常将其重命名
  • 重命名列
  • 将数据映射到特定列,默认情况下简单地提取 JSON
  • 允许数组和对象进行属性编码,例如 genre| 或 tags
  • 添加 csv 中不存在的列,例如状态或 createdAt
  • 调整数据,包括类型转换和应用正则表达式规则
  • @todo:映射相关表,例如 artwork.artist -> artist 表
  • 为过滤查询创建索引
  • meili 索引 pixie 文件

Pixie 特定的命名

在创建表时,我们在属性创建后添加一个 json 片段以指示一些属性。为了支持相关表和翻译,我们使用一些特定的列名,这些列名可能以 _ 或 __ 前缀

或者我们应该这样做?

  • _key:表的唯一键,可以由相关表使用
  • _attributes:所有不是属性的 JSON blob
  • _label:在另一个表中显示关系时使用的标签。可翻译。可定义
  • _description:我们最终将支持定义可翻译属性,但现在我们只支持 _description

事件/数据调整

在导入过程中,可以使用规则键重命名列,并使用格式化键调整数据。

此外,在将每一行插入 StorageBox 之前和之后,以及导入过程之前和之后,都会调用 RowEvent。这允许创建新字段或表,或清理需要服务的数据。

    #[AsEventListener(event: RowEvent::class)]
    public function onRowEvent(RowEvent $event): void
    {
        static $mun = []; // the array of municipios
        $row = $event->row;
        switch ($event->type) {
            case $event::POST_LOAD:
                ksort($mun);
                // save this to a new table or JSON file
                break;
            case $event::LOAD:
//                    https://#/MuseoGuadalupePosada?fref=ts -> MuseoGuadalupePosada
                if ($facebook = $row['facebook']??null) {
                    $parseUrl = parse_url($facebook);
                    $row['facebook'] = trim($parseUrl['path'],'/');
                }
                $mun[$row['municipio_id']] = $row['municipio'];
        }
    }

工作流程

可以使用工作流来处理涉及Web服务的数据,这样事件可以异步分发。例如,'增强'事件可以使用上面的facebook id获取最新的事件,或者最新的instagram帖子。

bin/console survos:make:workflow MexMus new,enhanced enhance --entity-class=Survos\\PixieBundle\\Model\\Item

然后

设置

所有Pixie数据库文件都有一个关联的配置文件,该文件描述了映射和底层数据结构。通常它与相同的基文件名相同。

curl 
bin/console pixie:init movies --dir=./data/imdb 
# ./pixie/movies.yaml created with 4 tables, configure it and run bin/console pixie:import movies --limit 10  
cat > pixie.movies << 'END'
(full config)
END
bin/console pixie:import movies --limit 10  
symfony open:local --path="/pixie/movies"

加载Pixie

由于数据目录(csv/json文件所在的位置)可以在任何地方,所以有几种方法来指示它们。

# explicitly 
bin/console pixie:import /path/to/csv/directory -c directory.yaml
# use source.dir key, absolute, or relative to bundle data_root).  If !exists, use the bundle data_root and append 'code'.
bin/console pixie:import -c code.yaml

有三种方法可以将数据加载到Pixie中。

“特殊”表

由于Pixie数据库提供了一种方便的方式与Excel数据一起工作,因此有一个特殊的表来处理绘图(嵌入式图像)。它是在bin/console grid:excel-to-csv(在grid-group包中?在museado中?)中创建的。

Excel将嵌入式图像存储为“绘图”。

翻译也以Pixie表的形式存储,并有自己的部分。

示例

  • 电影(imdb)
  • 学校

CSV数据集

读取现有的Pixie

$pixie = new Pixie::Reader('school.pixie');
$pixie->select('mo')
foreach ($pixie->)
wget https://dummyjson.com/products products.json
// inject the service

$id = 'tt123';
$kv = $pixieService->getStorageBox('dummy.pixie', [
    'products' => 'sku,brand,category' // first key is text primary key by default
]);

$kv->select('products'); // so that we don't have to pass it each time.

$kv->set($data); // because they key is in the data.
assert($kv->get($id));
assert($kv->has($id));
assert(json_decode($kv->get($id)) == $data);
//

conf文件简化了一些PHP调用,但不是必需的

假设我们想按类别过滤。首先,我们需要在表中添加一个索引,类似于dexie-style。

$kv = $pixieService->getStorageBox('app.db', [
    'movies' => 'imdb_id, year|integer, category|string' // first key is text primary key by default
]);

$rows = $kv->where("year < 2000 and category='drama'")->iterate();
// without the index
$rows = $kv->where("json_extract(value, '$.year') < 2000")->iterate();

通常CSV文件和其他数据源具有与sqlite列名不兼容的键名。要将旧名称映射到新名称,可以为列名创建一系列正则表达式规则。

从MOMA Artists.json

{
  "ConstituentID": 1,
  "DisplayName": "Robert Arneson",
  "ArtistBio": "American, 1930–1992",
  "Nationality": "American",
  "Gender": "male",
  "BeginDate": 1930,
  "EndDate": 1992,
  "Wiki QID": null
}
$kv->map([
   '/ConstituentID/' => 'id',
   '/BeginDate/' => 'birthYear',
   '/EndDate/' => 'deathYear'
], [
    'artists'
]);

所有字段都将转换为camel_case,即使没有正则表达式规则。

请注意,JSON未压缩,因此键被重复。因此,sqlite文件比CSV大(rowCount * headerRowSize)。

用法

composer require survos/pixie-bundle

使用sqlite数据库名称以及要创建的任何新表初始化StorageBox。

可以使用现有表,但禁用了自动表创建。

$kvDb = new StorageBox('translation.db', ['es', 'en'], 'en');
$key = md5('dog');
$kvDb->set($key, 'perro', 'es');
$kvDb->set($key, 'dog'); // defaults to en
$trans = $kvDb->get($key); // dog 
$trans = $kvDb->get($key, 'es'); // perro 
// trans is perro

// cache-like with callcack
$trans = $kvDb->get($key, callback: fn($item) => $this->translator->trans('dog'));

// keys are automatically slugified
$trans = $kvDb->get('My name is', fn($item) => $this->translator->trans($item->key));

// keys are automatically slugified
$trans = $kvDb->get('My name is',   ) => $this->translator->trans($item->key));

多语言StorageBox

特别适用于可能具有翻译的文本字段的kv查找

$kvDb = new MLSB('property.db', ['label','description']);

$key = 'Q31';
$kvDb->set($key, 'label', 'Belgium', 'en-gb');
$kvDb->set($key, 'description', 'constitutional monarchy in Western Europe', 'en-gb');

$transArray = $kvDb->getFieldsByLocale($key, 'en-gb'); 
// ['label' => 'Belgium'...]

$label = $kvDb->getField($key, 'label', 'en-gb'); 
// 'Belgium'

$transArray = $kvDb->getFields($key); 
// ['en-gb' => ['label' => 'Belgium', 'description'  => ...]]

// ditto for set, needs transactions

致谢

调试图标来自 https://www.svgrepo.com/svg/11690/database

备份

由于某种原因,.wal文件保持打开状态。我们需要一个工具来完成以下操作

  • 执行查询“vacuum into 'xx.backup.db'"
  • 压缩备份
  • 将备份移动到s3或bunny

要恢复,执行相反操作

  • 获取压缩的备份
  • 可选地重命名现有数据库
  • 删除 .wal等文件
  • 解压

S3示例

aws s3 sync . s3://voxitour/data/pixie --acl public-read --exclude="" --include="met.zip" aws s3 sync s3://voxitour/data/pixie . --acl public-read --exclude="" --include="met.zip"

aws s3 sync . s3://voxitour/data/pixie --acl public-read --exclude="" --include="x.pixie.db" aws s3 sync s3://voxitour/data/pixie . --acl public-read --exclude="" --include="x.pixie.db"

aws s3 sync s3://voxitour/data/pixie . --acl public-read --exclude="" --include=".zip"