mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-12 19:35:50 +00:00
296 lines
7.9 KiB
PHP
296 lines
7.9 KiB
PHP
<?php
|
|
|
|
namespace App\Module\ZincSearch;
|
|
|
|
use App\Module\Base;
|
|
|
|
/**
|
|
* ZincSearch 键值存储类
|
|
* 基于ZincSearch实现简单的键值存储功能
|
|
*
|
|
* 使用方法:
|
|
*
|
|
* 1. 基本操作
|
|
* - 设置键值: ZincSearchValue::set('site_name', '我的网站');
|
|
* - 设置复杂数据: ZincSearchValue::set('site_config', ['logo' => 'logo.png', 'theme' => 'dark']);
|
|
* - 合并现有数据: ZincSearchValue::set('site_config', ['footer' => '版权所有'], true);
|
|
* - 获取键值: $siteName = ZincSearchValue::get('site_name');
|
|
* - 获取键值带默认值: $theme = ZincSearchValue::get('theme', 'light');
|
|
* - 删除键值: ZincSearchValue::delete('temporary_data');
|
|
*
|
|
* 2. 批量操作
|
|
* - 批量设置: ZincSearchValue::batchSet(['user_count' => 100, 'active_users' => 50]);
|
|
* - 批量获取: $stats = ZincSearchValue::batchGet(['user_count', 'active_users']);
|
|
*
|
|
* 3. 其他操作
|
|
* - 清空所有数据: ZincSearchValue::clear();
|
|
*/
|
|
class ZincSearchKeyValue
|
|
{
|
|
/**
|
|
* 索引名称
|
|
*/
|
|
protected static string $indexName = 'keyValue';
|
|
|
|
// ==============================
|
|
// 基础方法
|
|
// ==============================
|
|
|
|
/**
|
|
* 确保索引存在
|
|
*/
|
|
private static function ensureIndex(): bool
|
|
{
|
|
if (!ZincSearchBase::indexExists(self::$indexName)) {
|
|
$mappings = [
|
|
'properties' => [
|
|
'key' => [
|
|
'type' => 'keyword',
|
|
'index' => true
|
|
],
|
|
'value' => [
|
|
'type' => 'text',
|
|
'index' => true
|
|
],
|
|
'created_at' => [
|
|
'type' => 'date',
|
|
'index' => true
|
|
],
|
|
'updated_at' => [
|
|
'type' => 'date',
|
|
'index' => true
|
|
]
|
|
]
|
|
];
|
|
$result = ZincSearchBase::createIndex(self::$indexName, $mappings);
|
|
return $result['success'] ?? false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// ==============================
|
|
// 基本操作
|
|
// ==============================
|
|
|
|
/**
|
|
* 设置键值
|
|
*
|
|
* @param string $key 键名
|
|
* @param mixed $value 值
|
|
* @param bool $merge 是否合并现有数据(如果值是数组)
|
|
* @return bool 是否成功
|
|
*/
|
|
public static function set(string $key, mixed $value, bool $merge = false): bool
|
|
{
|
|
if (!self::ensureIndex()) {
|
|
return false;
|
|
}
|
|
|
|
// 检查键是否已存在
|
|
if ($merge && is_array($value)) {
|
|
$existingData = self::get($key);
|
|
if (is_array($existingData)) {
|
|
$value = array_merge($existingData, $value);
|
|
}
|
|
}
|
|
|
|
// 检查是否存在相同键的文档
|
|
$searchResult = ZincSearchBase::search(self::$indexName, $key, 0, 1);
|
|
$docs = $searchResult['data']['hits']['hits'] ?? [];
|
|
$now = date('Y-m-d H:i:s');
|
|
|
|
if (!empty($docs)) {
|
|
$docId = $docs[0]['_id'] ?? null;
|
|
if ($docId) {
|
|
// 更新现有文档
|
|
$docData = [
|
|
'key' => $key,
|
|
'value' => $value,
|
|
'updated_at' => $now
|
|
];
|
|
$updateResult = ZincSearchBase::updateDoc(self::$indexName, $docId, $docData);
|
|
return $updateResult['success'] ?? false;
|
|
}
|
|
}
|
|
|
|
// 创建新文档
|
|
$docData = [
|
|
'key' => $key,
|
|
'value' => $value,
|
|
'created_at' => $now,
|
|
'updated_at' => $now
|
|
];
|
|
$addResult = ZincSearchBase::addDoc(self::$indexName, $docData);
|
|
return $addResult['success'] ?? false;
|
|
}
|
|
|
|
/**
|
|
* 获取键值
|
|
*
|
|
* @param string $key 键名
|
|
* @param mixed $default 默认值
|
|
* @return mixed 值或默认值
|
|
*/
|
|
public static function get(string $key, mixed $default = null): mixed
|
|
{
|
|
if (!self::ensureIndex() || empty($key)) {
|
|
return $default;
|
|
}
|
|
|
|
// 精确匹配键名
|
|
$searchParams = [
|
|
'search_type' => 'term',
|
|
'query' => [
|
|
'field' => 'key',
|
|
'term' => $key
|
|
],
|
|
'from' => 0,
|
|
'max_results' => 1
|
|
];
|
|
|
|
$result = ZincSearchBase::advancedSearch(self::$indexName, $searchParams);
|
|
if (!($result['success'] ?? false)) {
|
|
return $default;
|
|
}
|
|
|
|
$hits = $result['data']['hits']['hits'] ?? [];
|
|
if (empty($hits)) {
|
|
return $default;
|
|
}
|
|
|
|
return $hits[0]['_source']['value'] ?? $default;
|
|
}
|
|
|
|
/**
|
|
* 获取键值,返回数组
|
|
* @param string $key 键名
|
|
* @param array $default 默认值,当键不存在时返回
|
|
* @return array
|
|
*/
|
|
public static function getArray(string $key, array $default = []): array
|
|
{
|
|
return Base::string2array(self::get($key, $default));
|
|
}
|
|
|
|
/**
|
|
* 删除键值
|
|
*
|
|
* @param string $key 键名
|
|
* @return bool 是否成功
|
|
*/
|
|
public static function delete(string $key): bool
|
|
{
|
|
if (!self::ensureIndex() || empty($key)) {
|
|
return false;
|
|
}
|
|
|
|
// 查找文档ID
|
|
$searchParams = [
|
|
'search_type' => 'term',
|
|
'query' => [
|
|
'field' => 'key',
|
|
'term' => $key
|
|
],
|
|
'from' => 0,
|
|
'max_results' => 1
|
|
];
|
|
|
|
$result = ZincSearchBase::advancedSearch(self::$indexName, $searchParams);
|
|
if (!($result['success'] ?? false)) {
|
|
return false;
|
|
}
|
|
|
|
$hits = $result['data']['hits']['hits'] ?? [];
|
|
if (empty($hits)) {
|
|
return true; // 不存在视为删除成功
|
|
}
|
|
|
|
$docId = $hits[0]['_id'] ?? null;
|
|
if (empty($docId)) {
|
|
return false;
|
|
}
|
|
|
|
$deleteResult = ZincSearchBase::deleteDoc(self::$indexName, $docId);
|
|
return $deleteResult['success'] ?? false;
|
|
}
|
|
|
|
// ==============================
|
|
// 批量操作
|
|
// ==============================
|
|
|
|
/**
|
|
* 批量设置键值对
|
|
*
|
|
* @param array $keyValues 键值对数组
|
|
* @return bool 是否全部成功
|
|
*/
|
|
public static function batchSet(array $keyValues): bool
|
|
{
|
|
if (!self::ensureIndex() || empty($keyValues)) {
|
|
return false;
|
|
}
|
|
|
|
$docs = [];
|
|
$now = date('Y-m-d H:i:s');
|
|
|
|
foreach ($keyValues as $key => $value) {
|
|
$docs[] = [
|
|
'key' => $key,
|
|
'value' => $value,
|
|
'created_at' => $now,
|
|
'updated_at' => $now
|
|
];
|
|
}
|
|
|
|
$result = ZincSearchBase::addDocs(self::$indexName, $docs);
|
|
return $result['success'] ?? false;
|
|
}
|
|
|
|
/**
|
|
* 批量获取键值
|
|
*
|
|
* @param array $keys 键名数组
|
|
* @return array 键值对数组
|
|
*/
|
|
public static function batchGet(array $keys): array
|
|
{
|
|
if (!self::ensureIndex() || empty($keys)) {
|
|
return [];
|
|
}
|
|
|
|
$results = [];
|
|
|
|
// 遍历查询每个键
|
|
foreach ($keys as $key) {
|
|
$results[$key] = self::get($key);
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
// ==============================
|
|
// 其他操作
|
|
// ==============================
|
|
|
|
/**
|
|
* 清空所有键值
|
|
*
|
|
* @return bool 是否成功
|
|
*/
|
|
public static function clear(): bool
|
|
{
|
|
// 检查索引是否存在
|
|
if (!ZincSearchBase::indexExists(self::$indexName)) {
|
|
return true;
|
|
}
|
|
|
|
// 删除再重建索引
|
|
$deleteResult = ZincSearchBase::deleteIndex(self::$indexName);
|
|
if (!($deleteResult['success'] ?? false)) {
|
|
return false;
|
|
}
|
|
|
|
return self::ensureIndex();
|
|
}
|
|
}
|