refactor: 使用 Manticore Search 替换 SeekDB
This commit is contained in:
@@ -55,7 +55,7 @@ class Apps
|
||||
'drawio' => 'Drawio',
|
||||
'minder' => 'Minder',
|
||||
'search' => 'ZincSearch',
|
||||
'seekdb' => 'SeekDB',
|
||||
'manticore' => 'Manticore Search',
|
||||
default => $appId,
|
||||
};
|
||||
throw new ApiException("应用「{$name}」未安装", [], 0, false);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Module\SeekDB;
|
||||
namespace App\Module\Manticore;
|
||||
|
||||
use App\Models\File;
|
||||
use App\Models\FileContent;
|
||||
@@ -13,7 +13,7 @@ use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* SeekDB 文件搜索类
|
||||
* Manticore Search 文件搜索类
|
||||
*
|
||||
* 使用方法:
|
||||
*
|
||||
@@ -28,7 +28,7 @@ use Illuminate\Support\Facades\DB;
|
||||
* 3. 工具方法
|
||||
* - 清空索引: clear();
|
||||
*/
|
||||
class SeekDBFile
|
||||
class ManticoreFile
|
||||
{
|
||||
/**
|
||||
* 可搜索的文件类型
|
||||
@@ -83,18 +83,17 @@ class SeekDBFile
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
// 未安装 SeekDB,降级到 MySQL LIKE 搜索
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
// 未安装 Manticore,降级到 MySQL LIKE 搜索
|
||||
return self::searchByMysql($userid, $keyword, $from, $size);
|
||||
}
|
||||
|
||||
try {
|
||||
// 权限过滤已在 SeekDBBase 中通过 JOIN file_users 表实现
|
||||
switch ($searchType) {
|
||||
case 'text':
|
||||
// 纯全文搜索
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::fullTextSearch($keyword, $userid, $size, $from)
|
||||
ManticoreBase::fullTextSearch($keyword, $userid, $size, $from)
|
||||
);
|
||||
|
||||
case 'vector':
|
||||
@@ -103,11 +102,11 @@ class SeekDBFile
|
||||
if (empty($embedding)) {
|
||||
// embedding 获取失败,降级到全文搜索
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::fullTextSearch($keyword, $userid, $size, $from)
|
||||
ManticoreBase::fullTextSearch($keyword, $userid, $size, $from)
|
||||
);
|
||||
}
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::vectorSearch($embedding, $userid, $size)
|
||||
ManticoreBase::vectorSearch($embedding, $userid, $size)
|
||||
);
|
||||
|
||||
case 'hybrid':
|
||||
@@ -115,11 +114,11 @@ class SeekDBFile
|
||||
// 混合搜索
|
||||
$embedding = self::getEmbedding($keyword);
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::hybridSearch($keyword, $embedding, $userid, $size)
|
||||
ManticoreBase::hybridSearch($keyword, $embedding, $userid, $size)
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB search error: ' . $e->getMessage());
|
||||
Log::error('Manticore search error: ' . $e->getMessage());
|
||||
return self::searchByMysql($userid, $keyword, $from, $size);
|
||||
}
|
||||
}
|
||||
@@ -152,7 +151,7 @@ class SeekDBFile
|
||||
/**
|
||||
* 格式化搜索结果
|
||||
*
|
||||
* @param array $results SeekDB 返回的结果
|
||||
* @param array $results Manticore 返回的结果
|
||||
* @return array 格式化后的结果
|
||||
*/
|
||||
private static function formatSearchResults(array $results): array
|
||||
@@ -210,14 +209,14 @@ class SeekDBFile
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* 同步单个文件到 SeekDB
|
||||
* 同步单个文件到 Manticore
|
||||
*
|
||||
* @param File $file 文件模型
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function sync(File $file): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -229,7 +228,7 @@ class SeekDBFile
|
||||
// 根据文件类型检查大小限制
|
||||
$maxSize = self::getMaxFileSizeByExt($file->ext);
|
||||
if ($file->size > $maxSize) {
|
||||
Log::info("SeekDB: Skip large file {$file->id} ({$file->size} bytes, max: {$maxSize})");
|
||||
Log::info("Manticore: Skip large file {$file->id} ({$file->size} bytes, max: {$maxSize})");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -249,9 +248,8 @@ class SeekDBFile
|
||||
}
|
||||
}
|
||||
|
||||
// 写入 SeekDB
|
||||
// pshare 指向共享根文件夹的 ID,用于权限过滤
|
||||
$result = SeekDBBase::upsertFileVector([
|
||||
// 写入 Manticore
|
||||
$result = ManticoreBase::upsertFileVector([
|
||||
'file_id' => $file->id,
|
||||
'userid' => $file->userid,
|
||||
'pshare' => $file->pshare ?? 0,
|
||||
@@ -262,12 +260,9 @@ class SeekDBFile
|
||||
'content_vector' => $embedding,
|
||||
]);
|
||||
|
||||
// 注意:file_users 只需要同步共享文件夹的关系,不需要同步每个文件
|
||||
// 因为搜索时是通过 pshare 关联 file_users 表
|
||||
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB sync error: ' . $e->getMessage(), [
|
||||
Log::error('Manticore sync error: ' . $e->getMessage(), [
|
||||
'file_id' => $file->id,
|
||||
'file_name' => $file->name,
|
||||
]);
|
||||
@@ -314,7 +309,7 @@ class SeekDBFile
|
||||
*/
|
||||
public static function batchSync(iterable $files): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -335,11 +330,11 @@ class SeekDBFile
|
||||
*/
|
||||
public static function delete(int $fileId): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::deleteFileVector($fileId);
|
||||
return ManticoreBase::deleteFileVector($fileId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,11 +392,11 @@ class SeekDBFile
|
||||
*/
|
||||
public static function clear(): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::clearAllFileVectors();
|
||||
return ManticoreBase::clearAllFileVectors();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -411,11 +406,11 @@ class SeekDBFile
|
||||
*/
|
||||
public static function getIndexedCount(): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SeekDBBase::getIndexedFileCount();
|
||||
return ManticoreBase::getIndexedFileCount();
|
||||
}
|
||||
|
||||
// ==============================
|
||||
@@ -423,14 +418,14 @@ class SeekDBFile
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* 同步单个文件的用户关系到 SeekDB
|
||||
* 同步单个文件的用户关系到 Manticore
|
||||
*
|
||||
* @param int $fileId 文件ID
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function syncFileUsers(int $fileId): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $fileId <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $fileId <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -447,16 +442,16 @@ class SeekDBFile
|
||||
})
|
||||
->toArray();
|
||||
|
||||
// 同步到 SeekDB
|
||||
return SeekDBBase::syncFileUsers($fileId, $users);
|
||||
// 同步到 Manticore
|
||||
return ManticoreBase::syncFileUsers($fileId, $users);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB syncFileUsers error: ' . $e->getMessage(), ['file_id' => $fileId]);
|
||||
Log::error('Manticore syncFileUsers error: ' . $e->getMessage(), ['file_id' => $fileId]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文件用户关系到 SeekDB
|
||||
* 添加文件用户关系到 Manticore
|
||||
*
|
||||
* @param int $fileId 文件ID
|
||||
* @param int $userid 用户ID
|
||||
@@ -465,11 +460,11 @@ class SeekDBFile
|
||||
*/
|
||||
public static function addFileUser(int $fileId, int $userid, int $permission = 0): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $fileId <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $fileId <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::upsertFileUser($fileId, $userid, $permission);
|
||||
return ManticoreBase::upsertFileUser($fileId, $userid, $permission);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -481,15 +476,15 @@ class SeekDBFile
|
||||
*/
|
||||
public static function removeFileUser(int $fileId, ?int $userid = null): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $fileId <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $fileId <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($userid === null) {
|
||||
return SeekDBBase::deleteFileUsers($fileId);
|
||||
return ManticoreBase::deleteFileUsers($fileId);
|
||||
}
|
||||
|
||||
return SeekDBBase::deleteFileUser($fileId, $userid);
|
||||
return ManticoreBase::deleteFileUser($fileId, $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -500,7 +495,7 @@ class SeekDBFile
|
||||
*/
|
||||
public static function syncAllFileUsers(?callable $progressCallback = null): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -508,8 +503,8 @@ class SeekDBFile
|
||||
$lastId = 0;
|
||||
$batchSize = 1000;
|
||||
|
||||
// 先清空 SeekDB 中的 file_users 表
|
||||
SeekDBBase::clearAllFileUsers();
|
||||
// 先清空 Manticore 中的 file_users 表
|
||||
ManticoreBase::clearAllFileUsers();
|
||||
|
||||
// 分批同步
|
||||
while (true) {
|
||||
@@ -523,7 +518,7 @@ class SeekDBFile
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
SeekDBBase::upsertFileUser($record->file_id, $record->userid, $record->permission);
|
||||
ManticoreBase::upsertFileUser($record->file_id, $record->userid, $record->permission);
|
||||
$count++;
|
||||
$lastId = $record->id;
|
||||
}
|
||||
@@ -544,14 +539,14 @@ class SeekDBFile
|
||||
*/
|
||||
public static function syncFileUsersIncremental(?callable $progressCallback = null): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$batchSize = 1000;
|
||||
$lastKey = "sync:seekdbFileUserLastId";
|
||||
$lastId = intval(SeekDBKeyValue::get($lastKey, 0));
|
||||
$lastKey = "sync:manticoreFileUserLastId";
|
||||
$lastId = intval(ManticoreKeyValue::get($lastKey, 0));
|
||||
|
||||
// 分批同步新增的记录
|
||||
while (true) {
|
||||
@@ -565,13 +560,13 @@ class SeekDBFile
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
SeekDBBase::upsertFileUser($record->file_id, $record->userid, $record->permission);
|
||||
ManticoreBase::upsertFileUser($record->file_id, $record->userid, $record->permission);
|
||||
$count++;
|
||||
$lastId = $record->id;
|
||||
}
|
||||
|
||||
// 保存进度
|
||||
SeekDBKeyValue::set($lastKey, $lastId);
|
||||
ManticoreKeyValue::set($lastKey, $lastId);
|
||||
|
||||
if ($progressCallback) {
|
||||
$progressCallback($count);
|
||||
139
app/Module/Manticore/ManticoreKeyValue.php
Normal file
139
app/Module/Manticore/ManticoreKeyValue.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace App\Module\Manticore;
|
||||
|
||||
use App\Module\Apps;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Manticore Search 键值存储类
|
||||
*
|
||||
* 用于存储同步进度等配置信息
|
||||
*/
|
||||
class ManticoreKeyValue
|
||||
{
|
||||
/**
|
||||
* 获取值
|
||||
*
|
||||
* @param string $key 键
|
||||
* @param mixed $default 默认值
|
||||
* @return mixed 值
|
||||
*/
|
||||
public static function get(string $key, $default = null)
|
||||
{
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$instance = new ManticoreBase();
|
||||
$result = $instance->queryOne(
|
||||
"SELECT v FROM key_values WHERE k = ?",
|
||||
[$key]
|
||||
);
|
||||
|
||||
return $result ? $result['v'] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置值
|
||||
*
|
||||
* @param string $key 键
|
||||
* @param mixed $value 值
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function set(string $key, $value): bool
|
||||
{
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = new ManticoreBase();
|
||||
|
||||
// 先删除已存在的记录
|
||||
$instance->execute("DELETE FROM key_values WHERE k = ?", [$key]);
|
||||
|
||||
// 生成唯一 ID(基于 key 的 hash)
|
||||
$id = abs(crc32($key));
|
||||
|
||||
// 插入新记录
|
||||
return $instance->execute(
|
||||
"INSERT INTO key_values (id, k, v) VALUES (?, ?, ?)",
|
||||
[$id, $key, (string)$value]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除值
|
||||
*
|
||||
* @param string $key 键
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function delete(string $key): bool
|
||||
{
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = new ManticoreBase();
|
||||
return $instance->execute("DELETE FROM key_values WHERE k = ?", [$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有键值
|
||||
*
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function clear(): bool
|
||||
{
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = new ManticoreBase();
|
||||
return $instance->execute("TRUNCATE TABLE key_values");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查键是否存在
|
||||
*
|
||||
* @param string $key 键
|
||||
* @return bool 是否存在
|
||||
*/
|
||||
public static function exists(string $key): bool
|
||||
{
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = new ManticoreBase();
|
||||
$result = $instance->queryOne(
|
||||
"SELECT id FROM key_values WHERE k = ?",
|
||||
[$key]
|
||||
);
|
||||
|
||||
return $result !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有键值对
|
||||
*
|
||||
* @return array 键值对数组
|
||||
*/
|
||||
public static function all(): array
|
||||
{
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$instance = new ManticoreBase();
|
||||
$results = $instance->query("SELECT k, v FROM key_values");
|
||||
|
||||
$data = [];
|
||||
foreach ($results as $row) {
|
||||
$data[$row['k']] = $row['v'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Module\SeekDB;
|
||||
namespace App\Module\Manticore;
|
||||
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectUser;
|
||||
use App\Module\Apps;
|
||||
use App\Module\Base;
|
||||
use App\Module\AI;
|
||||
use App\Module\SeekDB\SeekDBKeyValue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* SeekDB 项目搜索类
|
||||
* Manticore Search 项目搜索类
|
||||
*
|
||||
* 使用方法:
|
||||
*
|
||||
@@ -31,7 +30,7 @@ use Illuminate\Support\Facades\Log;
|
||||
* 4. 工具方法
|
||||
* - 清空索引: clear();
|
||||
*/
|
||||
class SeekDBProject
|
||||
class ManticoreProject
|
||||
{
|
||||
/**
|
||||
* 搜索项目(支持全文、向量、混合搜索)
|
||||
@@ -48,7 +47,7 @@ class SeekDBProject
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -56,29 +55,29 @@ class SeekDBProject
|
||||
switch ($searchType) {
|
||||
case 'text':
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::projectFullTextSearch($keyword, $userid, $limit, 0)
|
||||
ManticoreBase::projectFullTextSearch($keyword, $userid, $limit, 0)
|
||||
);
|
||||
|
||||
case 'vector':
|
||||
$embedding = self::getEmbedding($keyword);
|
||||
if (empty($embedding)) {
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::projectFullTextSearch($keyword, $userid, $limit, 0)
|
||||
ManticoreBase::projectFullTextSearch($keyword, $userid, $limit, 0)
|
||||
);
|
||||
}
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::projectVectorSearch($embedding, $userid, $limit)
|
||||
ManticoreBase::projectVectorSearch($embedding, $userid, $limit)
|
||||
);
|
||||
|
||||
case 'hybrid':
|
||||
default:
|
||||
$embedding = self::getEmbedding($keyword);
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::projectHybridSearch($keyword, $embedding, $userid, $limit)
|
||||
ManticoreBase::projectHybridSearch($keyword, $embedding, $userid, $limit)
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB project search error: ' . $e->getMessage());
|
||||
Log::error('Manticore project search error: ' . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -110,7 +109,7 @@ class SeekDBProject
|
||||
/**
|
||||
* 格式化搜索结果
|
||||
*
|
||||
* @param array $results SeekDB 返回的结果
|
||||
* @param array $results Manticore 返回的结果
|
||||
* @return array 格式化后的结果
|
||||
*/
|
||||
private static function formatSearchResults(array $results): array
|
||||
@@ -135,14 +134,14 @@ class SeekDBProject
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* 同步单个项目到 SeekDB
|
||||
* 同步单个项目到 Manticore
|
||||
*
|
||||
* @param Project $project 项目模型
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function sync(Project $project): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -164,8 +163,8 @@ class SeekDBProject
|
||||
}
|
||||
}
|
||||
|
||||
// 写入 SeekDB
|
||||
$result = SeekDBBase::upsertProjectVector([
|
||||
// 写入 Manticore
|
||||
$result = ManticoreBase::upsertProjectVector([
|
||||
'project_id' => $project->id,
|
||||
'userid' => $project->userid ?? 0,
|
||||
'personal' => $project->personal ?? 0,
|
||||
@@ -176,7 +175,7 @@ class SeekDBProject
|
||||
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB project sync error: ' . $e->getMessage(), [
|
||||
Log::error('Manticore project sync error: ' . $e->getMessage(), [
|
||||
'project_id' => $project->id,
|
||||
'project_name' => $project->name,
|
||||
]);
|
||||
@@ -212,7 +211,7 @@ class SeekDBProject
|
||||
*/
|
||||
public static function batchSync(iterable $projects): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -233,14 +232,14 @@ class SeekDBProject
|
||||
*/
|
||||
public static function delete(int $projectId): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 删除项目索引
|
||||
SeekDBBase::deleteProjectVector($projectId);
|
||||
ManticoreBase::deleteProjectVector($projectId);
|
||||
// 删除项目成员关系
|
||||
SeekDBBase::deleteAllProjectUsers($projectId);
|
||||
ManticoreBase::deleteAllProjectUsers($projectId);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -252,12 +251,12 @@ class SeekDBProject
|
||||
*/
|
||||
public static function clear(): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SeekDBBase::clearAllProjectVectors();
|
||||
SeekDBBase::clearAllProjectUsers();
|
||||
ManticoreBase::clearAllProjectVectors();
|
||||
ManticoreBase::clearAllProjectUsers();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -269,11 +268,11 @@ class SeekDBProject
|
||||
*/
|
||||
public static function getIndexedCount(): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SeekDBBase::getIndexedProjectCount();
|
||||
return ManticoreBase::getIndexedProjectCount();
|
||||
}
|
||||
|
||||
// ==============================
|
||||
@@ -281,7 +280,7 @@ class SeekDBProject
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* 添加项目成员到 SeekDB
|
||||
* 添加项目成员到 Manticore
|
||||
*
|
||||
* @param int $projectId 项目ID
|
||||
* @param int $userid 用户ID
|
||||
@@ -289,11 +288,11 @@ class SeekDBProject
|
||||
*/
|
||||
public static function addProjectUser(int $projectId, int $userid): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $projectId <= 0 || $userid <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $projectId <= 0 || $userid <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::upsertProjectUser($projectId, $userid);
|
||||
return ManticoreBase::upsertProjectUser($projectId, $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,22 +304,22 @@ class SeekDBProject
|
||||
*/
|
||||
public static function removeProjectUser(int $projectId, int $userid): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $projectId <= 0 || $userid <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $projectId <= 0 || $userid <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::deleteProjectUser($projectId, $userid);
|
||||
return ManticoreBase::deleteProjectUser($projectId, $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步项目的所有成员到 SeekDB
|
||||
* 同步项目的所有成员到 Manticore
|
||||
*
|
||||
* @param int $projectId 项目ID
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function syncProjectUsers(int $projectId): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $projectId <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $projectId <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -330,10 +329,10 @@ class SeekDBProject
|
||||
->pluck('userid')
|
||||
->toArray();
|
||||
|
||||
// 同步到 SeekDB
|
||||
return SeekDBBase::syncProjectUsers($projectId, $userids);
|
||||
// 同步到 Manticore
|
||||
return ManticoreBase::syncProjectUsers($projectId, $userids);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB syncProjectUsers error: ' . $e->getMessage(), ['project_id' => $projectId]);
|
||||
Log::error('Manticore syncProjectUsers error: ' . $e->getMessage(), ['project_id' => $projectId]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -346,7 +345,7 @@ class SeekDBProject
|
||||
*/
|
||||
public static function syncAllProjectUsers(?callable $progressCallback = null): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -354,8 +353,8 @@ class SeekDBProject
|
||||
$lastId = 0;
|
||||
$batchSize = 1000;
|
||||
|
||||
// 先清空 SeekDB 中的 project_users 表
|
||||
SeekDBBase::clearAllProjectUsers();
|
||||
// 先清空 Manticore 中的 project_users 表
|
||||
ManticoreBase::clearAllProjectUsers();
|
||||
|
||||
// 分批同步
|
||||
while (true) {
|
||||
@@ -369,7 +368,7 @@ class SeekDBProject
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
SeekDBBase::upsertProjectUser($record->project_id, $record->userid);
|
||||
ManticoreBase::upsertProjectUser($record->project_id, $record->userid);
|
||||
$count++;
|
||||
$lastId = $record->id;
|
||||
}
|
||||
@@ -390,14 +389,14 @@ class SeekDBProject
|
||||
*/
|
||||
public static function syncProjectUsersIncremental(?callable $progressCallback = null): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$batchSize = 1000;
|
||||
$lastKey = "sync:seekdbProjectUserLastId";
|
||||
$lastId = intval(SeekDBKeyValue::get($lastKey, 0));
|
||||
$lastKey = "sync:manticoreProjectUserLastId";
|
||||
$lastId = intval(ManticoreKeyValue::get($lastKey, 0));
|
||||
|
||||
// 分批同步新增的记录
|
||||
while (true) {
|
||||
@@ -411,13 +410,13 @@ class SeekDBProject
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
SeekDBBase::upsertProjectUser($record->project_id, $record->userid);
|
||||
ManticoreBase::upsertProjectUser($record->project_id, $record->userid);
|
||||
$count++;
|
||||
$lastId = $record->id;
|
||||
}
|
||||
|
||||
// 保存进度
|
||||
SeekDBKeyValue::set($lastKey, $lastId);
|
||||
ManticoreKeyValue::set($lastKey, $lastId);
|
||||
|
||||
if ($progressCallback) {
|
||||
$progressCallback($count);
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Module\SeekDB;
|
||||
namespace App\Module\Manticore;
|
||||
|
||||
use App\Models\ProjectTask;
|
||||
use App\Models\ProjectTaskContent;
|
||||
@@ -9,11 +9,10 @@ use App\Models\ProjectTaskVisibilityUser;
|
||||
use App\Module\Apps;
|
||||
use App\Module\Base;
|
||||
use App\Module\AI;
|
||||
use App\Module\SeekDB\SeekDBKeyValue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* SeekDB 任务搜索类
|
||||
* Manticore Search 任务搜索类
|
||||
*
|
||||
* 权限逻辑说明:
|
||||
* - visibility = 1: 项目人员可见,通过 project_users 表过滤
|
||||
@@ -38,7 +37,7 @@ use Illuminate\Support\Facades\Log;
|
||||
* 4. 工具方法
|
||||
* - 清空索引: clear();
|
||||
*/
|
||||
class SeekDBTask
|
||||
class ManticoreTask
|
||||
{
|
||||
/**
|
||||
* 最大内容长度(字符)
|
||||
@@ -60,7 +59,7 @@ class SeekDBTask
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -68,29 +67,29 @@ class SeekDBTask
|
||||
switch ($searchType) {
|
||||
case 'text':
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::taskFullTextSearch($keyword, $userid, $limit, 0)
|
||||
ManticoreBase::taskFullTextSearch($keyword, $userid, $limit, 0)
|
||||
);
|
||||
|
||||
case 'vector':
|
||||
$embedding = self::getEmbedding($keyword);
|
||||
if (empty($embedding)) {
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::taskFullTextSearch($keyword, $userid, $limit, 0)
|
||||
ManticoreBase::taskFullTextSearch($keyword, $userid, $limit, 0)
|
||||
);
|
||||
}
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::taskVectorSearch($embedding, $userid, $limit)
|
||||
ManticoreBase::taskVectorSearch($embedding, $userid, $limit)
|
||||
);
|
||||
|
||||
case 'hybrid':
|
||||
default:
|
||||
$embedding = self::getEmbedding($keyword);
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::taskHybridSearch($keyword, $embedding, $userid, $limit)
|
||||
ManticoreBase::taskHybridSearch($keyword, $embedding, $userid, $limit)
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB task search error: ' . $e->getMessage());
|
||||
Log::error('Manticore task search error: ' . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -122,7 +121,7 @@ class SeekDBTask
|
||||
/**
|
||||
* 格式化搜索结果
|
||||
*
|
||||
* @param array $results SeekDB 返回的结果
|
||||
* @param array $results Manticore 返回的结果
|
||||
* @return array 格式化后的结果
|
||||
*/
|
||||
private static function formatSearchResults(array $results): array
|
||||
@@ -149,14 +148,14 @@ class SeekDBTask
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* 同步单个任务到 SeekDB
|
||||
* 同步单个任务到 Manticore
|
||||
*
|
||||
* @param ProjectTask $task 任务模型
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function sync(ProjectTask $task): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -181,8 +180,8 @@ class SeekDBTask
|
||||
}
|
||||
}
|
||||
|
||||
// 写入 SeekDB
|
||||
$result = SeekDBBase::upsertTaskVector([
|
||||
// 写入 Manticore
|
||||
$result = ManticoreBase::upsertTaskVector([
|
||||
'task_id' => $task->id,
|
||||
'project_id' => $task->project_id ?? 0,
|
||||
'userid' => $task->userid ?? 0,
|
||||
@@ -195,7 +194,7 @@ class SeekDBTask
|
||||
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB task sync error: ' . $e->getMessage(), [
|
||||
Log::error('Manticore task sync error: ' . $e->getMessage(), [
|
||||
'task_id' => $task->id,
|
||||
'task_name' => $task->name,
|
||||
]);
|
||||
@@ -298,7 +297,7 @@ class SeekDBTask
|
||||
*/
|
||||
public static function batchSync(iterable $tasks): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -319,14 +318,14 @@ class SeekDBTask
|
||||
*/
|
||||
public static function delete(int $taskId): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 删除任务索引
|
||||
SeekDBBase::deleteTaskVector($taskId);
|
||||
ManticoreBase::deleteTaskVector($taskId);
|
||||
// 删除任务成员关系
|
||||
SeekDBBase::deleteAllTaskUsers($taskId);
|
||||
ManticoreBase::deleteAllTaskUsers($taskId);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -340,11 +339,11 @@ class SeekDBTask
|
||||
*/
|
||||
public static function updateVisibility(int $taskId, int $visibility): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $taskId <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $taskId <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::updateTaskVisibility($taskId, $visibility);
|
||||
return ManticoreBase::updateTaskVisibility($taskId, $visibility);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,12 +353,12 @@ class SeekDBTask
|
||||
*/
|
||||
public static function clear(): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SeekDBBase::clearAllTaskVectors();
|
||||
SeekDBBase::clearAllTaskUsers();
|
||||
ManticoreBase::clearAllTaskVectors();
|
||||
ManticoreBase::clearAllTaskUsers();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -371,11 +370,11 @@ class SeekDBTask
|
||||
*/
|
||||
public static function getIndexedCount(): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SeekDBBase::getIndexedTaskCount();
|
||||
return ManticoreBase::getIndexedTaskCount();
|
||||
}
|
||||
|
||||
// ==============================
|
||||
@@ -383,7 +382,7 @@ class SeekDBTask
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* 添加任务成员到 SeekDB
|
||||
* 添加任务成员到 Manticore
|
||||
*
|
||||
* @param int $taskId 任务ID
|
||||
* @param int $userid 用户ID
|
||||
@@ -391,11 +390,11 @@ class SeekDBTask
|
||||
*/
|
||||
public static function addTaskUser(int $taskId, int $userid): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $taskId <= 0 || $userid <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $taskId <= 0 || $userid <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::upsertTaskUser($taskId, $userid);
|
||||
return ManticoreBase::upsertTaskUser($taskId, $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -407,11 +406,11 @@ class SeekDBTask
|
||||
*/
|
||||
public static function removeTaskUser(int $taskId, int $userid): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $taskId <= 0 || $userid <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $taskId <= 0 || $userid <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::deleteTaskUser($taskId, $userid);
|
||||
return ManticoreBase::deleteTaskUser($taskId, $userid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,7 +425,7 @@ class SeekDBTask
|
||||
*/
|
||||
public static function removeVisibilityUser(int $taskId, int $userid): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $taskId <= 0 || $userid <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $taskId <= 0 || $userid <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -450,10 +449,10 @@ class SeekDBTask
|
||||
return true;
|
||||
}
|
||||
|
||||
// 从 SeekDB 删除
|
||||
return SeekDBBase::deleteTaskUser($taskId, $userid);
|
||||
// 从 Manticore 删除
|
||||
return ManticoreBase::deleteTaskUser($taskId, $userid);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB removeVisibilityUser error: ' . $e->getMessage(), [
|
||||
Log::error('Manticore removeVisibilityUser error: ' . $e->getMessage(), [
|
||||
'task_id' => $taskId,
|
||||
'userid' => $userid,
|
||||
]);
|
||||
@@ -462,7 +461,7 @@ class SeekDBTask
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步任务的所有成员到 SeekDB
|
||||
* 同步任务的所有成员到 Manticore
|
||||
*
|
||||
* 包括:ProjectTaskUser 和 ProjectTaskVisibilityUser
|
||||
*
|
||||
@@ -471,7 +470,7 @@ class SeekDBTask
|
||||
*/
|
||||
public static function syncTaskUsers(int $taskId): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || $taskId <= 0) {
|
||||
if (!Apps::isInstalled("manticore") || $taskId <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -490,10 +489,10 @@ class SeekDBTask
|
||||
// 合并去重
|
||||
$allUserIds = array_unique(array_merge($taskUserIds, $visibilityUserIds));
|
||||
|
||||
// 同步到 SeekDB
|
||||
return SeekDBBase::syncTaskUsers($taskId, $allUserIds);
|
||||
// 同步到 Manticore
|
||||
return ManticoreBase::syncTaskUsers($taskId, $allUserIds);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB syncTaskUsers error: ' . $e->getMessage(), ['task_id' => $taskId]);
|
||||
Log::error('Manticore syncTaskUsers error: ' . $e->getMessage(), ['task_id' => $taskId]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -506,7 +505,7 @@ class SeekDBTask
|
||||
*/
|
||||
public static function syncAllTaskUsers(?callable $progressCallback = null): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -514,8 +513,8 @@ class SeekDBTask
|
||||
$lastId = 0;
|
||||
$batchSize = 1000;
|
||||
|
||||
// 先清空 SeekDB 中的 task_users 表
|
||||
SeekDBBase::clearAllTaskUsers();
|
||||
// 先清空 Manticore 中的 task_users 表
|
||||
ManticoreBase::clearAllTaskUsers();
|
||||
|
||||
// 同步 ProjectTaskUser
|
||||
while (true) {
|
||||
@@ -529,10 +528,10 @@ class SeekDBTask
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
SeekDBBase::upsertTaskUser($record->task_id, $record->userid);
|
||||
ManticoreBase::upsertTaskUser($record->task_id, $record->userid);
|
||||
// 如果有父任务,也添加到父任务
|
||||
if ($record->task_pid) {
|
||||
SeekDBBase::upsertTaskUser($record->task_pid, $record->userid);
|
||||
ManticoreBase::upsertTaskUser($record->task_pid, $record->userid);
|
||||
}
|
||||
$count++;
|
||||
$lastId = $record->id;
|
||||
@@ -556,7 +555,7 @@ class SeekDBTask
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
SeekDBBase::upsertTaskUser($record->task_id, $record->userid);
|
||||
ManticoreBase::upsertTaskUser($record->task_id, $record->userid);
|
||||
$count++;
|
||||
$lastId = $record->id;
|
||||
}
|
||||
@@ -577,7 +576,7 @@ class SeekDBTask
|
||||
*/
|
||||
public static function syncTaskUsersIncremental(?callable $progressCallback = null): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -585,8 +584,8 @@ class SeekDBTask
|
||||
$batchSize = 1000;
|
||||
|
||||
// 同步 ProjectTaskUser 新增
|
||||
$lastKey1 = "sync:seekdbTaskUserLastId";
|
||||
$lastId1 = intval(SeekDBKeyValue::get($lastKey1, 0));
|
||||
$lastKey1 = "sync:manticoreTaskUserLastId";
|
||||
$lastId1 = intval(ManticoreKeyValue::get($lastKey1, 0));
|
||||
|
||||
while (true) {
|
||||
$records = ProjectTaskUser::where('id', '>', $lastId1)
|
||||
@@ -599,15 +598,15 @@ class SeekDBTask
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
SeekDBBase::upsertTaskUser($record->task_id, $record->userid);
|
||||
ManticoreBase::upsertTaskUser($record->task_id, $record->userid);
|
||||
if ($record->task_pid) {
|
||||
SeekDBBase::upsertTaskUser($record->task_pid, $record->userid);
|
||||
ManticoreBase::upsertTaskUser($record->task_pid, $record->userid);
|
||||
}
|
||||
$count++;
|
||||
$lastId1 = $record->id;
|
||||
}
|
||||
|
||||
SeekDBKeyValue::set($lastKey1, $lastId1);
|
||||
ManticoreKeyValue::set($lastKey1, $lastId1);
|
||||
|
||||
if ($progressCallback) {
|
||||
$progressCallback($count);
|
||||
@@ -615,8 +614,8 @@ class SeekDBTask
|
||||
}
|
||||
|
||||
// 同步 ProjectTaskVisibilityUser 新增
|
||||
$lastKey2 = "sync:seekdbTaskVisibilityUserLastId";
|
||||
$lastId2 = intval(SeekDBKeyValue::get($lastKey2, 0));
|
||||
$lastKey2 = "sync:manticoreTaskVisibilityUserLastId";
|
||||
$lastId2 = intval(ManticoreKeyValue::get($lastKey2, 0));
|
||||
|
||||
while (true) {
|
||||
$records = ProjectTaskVisibilityUser::where('id', '>', $lastId2)
|
||||
@@ -629,12 +628,12 @@ class SeekDBTask
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
SeekDBBase::upsertTaskUser($record->task_id, $record->userid);
|
||||
ManticoreBase::upsertTaskUser($record->task_id, $record->userid);
|
||||
$count++;
|
||||
$lastId2 = $record->id;
|
||||
}
|
||||
|
||||
SeekDBKeyValue::set($lastKey2, $lastId2);
|
||||
ManticoreKeyValue::set($lastKey2, $lastId2);
|
||||
|
||||
if ($progressCallback) {
|
||||
$progressCallback($count);
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Module\SeekDB;
|
||||
namespace App\Module\Manticore;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Module\Apps;
|
||||
@@ -9,7 +9,7 @@ use App\Module\AI;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* SeekDB 用户搜索类(联系人搜索)
|
||||
* Manticore Search 用户搜索类(联系人搜索)
|
||||
*
|
||||
* 使用方法:
|
||||
*
|
||||
@@ -24,7 +24,7 @@ use Illuminate\Support\Facades\Log;
|
||||
* 3. 工具方法
|
||||
* - 清空索引: clear();
|
||||
*/
|
||||
class SeekDBUser
|
||||
class ManticoreUser
|
||||
{
|
||||
/**
|
||||
* 搜索用户(支持全文、向量、混合搜索)
|
||||
@@ -40,7 +40,7 @@ class SeekDBUser
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -48,29 +48,29 @@ class SeekDBUser
|
||||
switch ($searchType) {
|
||||
case 'text':
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::userFullTextSearch($keyword, $limit, 0)
|
||||
ManticoreBase::userFullTextSearch($keyword, $limit, 0)
|
||||
);
|
||||
|
||||
case 'vector':
|
||||
$embedding = self::getEmbedding($keyword);
|
||||
if (empty($embedding)) {
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::userFullTextSearch($keyword, $limit, 0)
|
||||
ManticoreBase::userFullTextSearch($keyword, $limit, 0)
|
||||
);
|
||||
}
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::userVectorSearch($embedding, $limit)
|
||||
ManticoreBase::userVectorSearch($embedding, $limit)
|
||||
);
|
||||
|
||||
case 'hybrid':
|
||||
default:
|
||||
$embedding = self::getEmbedding($keyword);
|
||||
return self::formatSearchResults(
|
||||
SeekDBBase::userHybridSearch($keyword, $embedding, $limit)
|
||||
ManticoreBase::userHybridSearch($keyword, $embedding, $limit)
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB user search error: ' . $e->getMessage());
|
||||
Log::error('Manticore user search error: ' . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ class SeekDBUser
|
||||
/**
|
||||
* 格式化搜索结果
|
||||
*
|
||||
* @param array $results SeekDB 返回的结果
|
||||
* @param array $results Manticore 返回的结果
|
||||
* @return array 格式化后的结果
|
||||
*/
|
||||
private static function formatSearchResults(array $results): array
|
||||
@@ -127,14 +127,14 @@ class SeekDBUser
|
||||
// ==============================
|
||||
|
||||
/**
|
||||
* 同步单个用户到 SeekDB
|
||||
* 同步单个用户到 Manticore
|
||||
*
|
||||
* @param User $user 用户模型
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function sync(User $user): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -161,8 +161,8 @@ class SeekDBUser
|
||||
}
|
||||
}
|
||||
|
||||
// 写入 SeekDB
|
||||
$result = SeekDBBase::upsertUserVector([
|
||||
// 写入 Manticore
|
||||
$result = ManticoreBase::upsertUserVector([
|
||||
'userid' => $user->userid,
|
||||
'nickname' => $user->nickname ?? '',
|
||||
'email' => $user->email ?? '',
|
||||
@@ -174,7 +174,7 @@ class SeekDBUser
|
||||
|
||||
return $result;
|
||||
} catch (\Exception $e) {
|
||||
Log::error('SeekDB user sync error: ' . $e->getMessage(), [
|
||||
Log::error('Manticore user sync error: ' . $e->getMessage(), [
|
||||
'userid' => $user->userid,
|
||||
'nickname' => $user->nickname,
|
||||
]);
|
||||
@@ -216,7 +216,7 @@ class SeekDBUser
|
||||
*/
|
||||
public static function batchSync(iterable $users): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -237,11 +237,11 @@ class SeekDBUser
|
||||
*/
|
||||
public static function delete(int $userid): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::deleteUserVector($userid);
|
||||
return ManticoreBase::deleteUserVector($userid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,11 +251,11 @@ class SeekDBUser
|
||||
*/
|
||||
public static function clear(): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SeekDBBase::clearAllUserVectors();
|
||||
return ManticoreBase::clearAllUserVectors();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,11 +265,11 @@ class SeekDBUser
|
||||
*/
|
||||
public static function getIndexedCount(): int
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
if (!Apps::isInstalled("manticore")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return SeekDBBase::getIndexedUserCount();
|
||||
return ManticoreBase::getIndexedUserCount();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Module\SeekDB;
|
||||
|
||||
use App\Module\Apps;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* SeekDB 键值存储类
|
||||
*
|
||||
* 用于存储同步进度、配置等键值数据
|
||||
*
|
||||
* 使用方法:
|
||||
*
|
||||
* 1. 基本操作
|
||||
* - 设置键值: set('sync_last_id', 12345);
|
||||
* - 获取键值: $lastId = get('sync_last_id', 0);
|
||||
* - 删除键值: delete('sync_last_id');
|
||||
*
|
||||
* 2. 批量操作
|
||||
* - 批量设置: batchSet(['key1' => 'value1', 'key2' => 'value2']);
|
||||
* - 批量获取: $values = batchGet(['key1', 'key2']);
|
||||
*/
|
||||
class SeekDBKeyValue
|
||||
{
|
||||
/**
|
||||
* 设置键值
|
||||
*
|
||||
* @param string $key 键名
|
||||
* @param mixed $value 值(会被 JSON 编码)
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function set(string $key, mixed $value): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || empty($key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = new SeekDBBase();
|
||||
$jsonValue = is_string($value) ? $value : json_encode($value, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// 使用 REPLACE INTO 实现 upsert
|
||||
$sql = "REPLACE INTO key_values (k, v, updated_at) VALUES (?, ?, NOW())";
|
||||
|
||||
return $instance->execute($sql, [$key, $jsonValue]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取键值
|
||||
*
|
||||
* @param string $key 键名
|
||||
* @param mixed $default 默认值
|
||||
* @return mixed 值或默认值
|
||||
*/
|
||||
public static function get(string $key, mixed $default = null): mixed
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || empty($key)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$instance = new SeekDBBase();
|
||||
$result = $instance->queryOne(
|
||||
"SELECT v FROM key_values WHERE k = ?",
|
||||
[$key]
|
||||
);
|
||||
|
||||
if (!$result || !isset($result['v'])) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$value = $result['v'];
|
||||
|
||||
// 尝试 JSON 解码
|
||||
$decoded = json_decode($value, true);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除键值
|
||||
*
|
||||
* @param string $key 键名
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function delete(string $key): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || empty($key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = new SeekDBBase();
|
||||
return $instance->execute(
|
||||
"DELETE FROM key_values WHERE k = ?",
|
||||
[$key]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量设置键值
|
||||
*
|
||||
* @param array $keyValues 键值对数组
|
||||
* @return bool 是否全部成功
|
||||
*/
|
||||
public static function batchSet(array $keyValues): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || empty($keyValues)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = new SeekDBBase();
|
||||
$success = true;
|
||||
|
||||
foreach ($keyValues as $key => $value) {
|
||||
$jsonValue = is_string($value) ? $value : json_encode($value, JSON_UNESCAPED_UNICODE);
|
||||
$result = $instance->execute(
|
||||
"REPLACE INTO key_values (k, v, updated_at) VALUES (?, ?, NOW())",
|
||||
[$key, $jsonValue]
|
||||
);
|
||||
if (!$result) {
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取键值
|
||||
*
|
||||
* @param array $keys 键名数组
|
||||
* @return array 键值对数组
|
||||
*/
|
||||
public static function batchGet(array $keys): array
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb") || empty($keys)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$instance = new SeekDBBase();
|
||||
$placeholders = implode(',', array_fill(0, count($keys), '?'));
|
||||
$results = $instance->query(
|
||||
"SELECT k, v FROM key_values WHERE k IN ({$placeholders})",
|
||||
$keys
|
||||
);
|
||||
|
||||
$values = [];
|
||||
foreach ($results as $row) {
|
||||
$value = $row['v'];
|
||||
$decoded = json_decode($value, true);
|
||||
$values[$row['k']] = (json_last_error() === JSON_ERROR_NONE) ? $decoded : $value;
|
||||
}
|
||||
|
||||
// 填充未找到的键为 null
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($values[$key])) {
|
||||
$values[$key] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有键值
|
||||
*
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
public static function clear(): bool
|
||||
{
|
||||
if (!Apps::isInstalled("seekdb")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = new SeekDBBase();
|
||||
return $instance->execute("TRUNCATE TABLE key_values");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user