Refactor homepage for focused search and data display; streamline data platform; enhance user and tag management; focus AI assistant on data analysis and report generation. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
434 lines
11 KiB
TypeScript
434 lines
11 KiB
TypeScript
// MindsDB连接器 - 实现AI增强的数据查询和分析
|
||
import { Client } from "mindsdb-js-sdk"
|
||
|
||
export interface MindsDBConfig {
|
||
host: string
|
||
port: number
|
||
username: string
|
||
password: string
|
||
database?: string
|
||
}
|
||
|
||
export interface AIQueryRequest {
|
||
query: string
|
||
model?: string
|
||
parameters?: Record<string, any>
|
||
useCache?: boolean
|
||
}
|
||
|
||
export interface SearchRequest {
|
||
keyword: string
|
||
type: "user" | "traffic" | "all"
|
||
filters?: Record<string, any>
|
||
limit?: number
|
||
offset?: number
|
||
}
|
||
|
||
export interface VersionInfo {
|
||
version: string
|
||
timestamp: string
|
||
changes: string[]
|
||
author: string
|
||
}
|
||
|
||
export class MindsDBConnector {
|
||
private client: Client
|
||
private connected = false
|
||
private cache: Map<string, any> = new Map()
|
||
|
||
constructor(private config: MindsDBConfig) {
|
||
this.client = new Client({
|
||
host: config.host,
|
||
port: config.port,
|
||
username: config.username,
|
||
password: config.password,
|
||
})
|
||
}
|
||
|
||
// 连接到MindsDB
|
||
async connect(): Promise<void> {
|
||
try {
|
||
await this.client.connect()
|
||
this.connected = true
|
||
console.log("MindsDB连接成功")
|
||
} catch (error) {
|
||
console.error("MindsDB连接失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 断开连接
|
||
async disconnect(): Promise<void> {
|
||
if (this.connected) {
|
||
await this.client.disconnect()
|
||
this.connected = false
|
||
}
|
||
}
|
||
|
||
// AI增强查询 - 使用自然语言查询数据
|
||
async aiQuery(request: AIQueryRequest): Promise<any> {
|
||
if (!this.connected) {
|
||
await this.connect()
|
||
}
|
||
|
||
const cacheKey = `ai_query_${JSON.stringify(request)}`
|
||
|
||
// 检查缓存
|
||
if (request.useCache && this.cache.has(cacheKey)) {
|
||
return this.cache.get(cacheKey)
|
||
}
|
||
|
||
try {
|
||
// 使用MindsDB的AI模型进行查询
|
||
const query = `
|
||
SELECT * FROM mindsdb.${request.model || "gpt4"}
|
||
WHERE text = '${request.query}'
|
||
`
|
||
|
||
const result = await this.client.query(query)
|
||
|
||
// 缓存结果
|
||
if (request.useCache) {
|
||
this.cache.set(cacheKey, result, 300000) // 5分钟缓存
|
||
}
|
||
|
||
return result
|
||
} catch (error) {
|
||
console.error("AI查询失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 智能搜索 - 支持用户数据和流量关键词的快速搜索
|
||
async intelligentSearch(request: SearchRequest): Promise<any> {
|
||
if (!this.connected) {
|
||
await this.connect()
|
||
}
|
||
|
||
const cacheKey = `search_${JSON.stringify(request)}`
|
||
|
||
// 检查缓存
|
||
if (this.cache.has(cacheKey)) {
|
||
return this.cache.get(cacheKey)
|
||
}
|
||
|
||
try {
|
||
let searchQuery = ""
|
||
|
||
switch (request.type) {
|
||
case "user":
|
||
searchQuery = this.buildUserSearchQuery(request)
|
||
break
|
||
case "traffic":
|
||
searchQuery = this.buildTrafficSearchQuery(request)
|
||
break
|
||
case "all":
|
||
searchQuery = this.buildUnifiedSearchQuery(request)
|
||
break
|
||
}
|
||
|
||
const result = await this.client.query(searchQuery)
|
||
|
||
// 缓存结果
|
||
this.cache.set(cacheKey, result, 60000) // 1分钟缓存
|
||
|
||
return result
|
||
} catch (error) {
|
||
console.error("智能搜索失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 构建用户搜索查询
|
||
private buildUserSearchQuery(request: SearchRequest): string {
|
||
const { keyword, filters, limit = 100, offset = 0 } = request
|
||
|
||
let query = `
|
||
SELECT
|
||
u.user_id,
|
||
u.username,
|
||
u.phone,
|
||
u.email,
|
||
u.tags,
|
||
u.rfm_score,
|
||
u.last_active,
|
||
u.created_at,
|
||
MATCH(u.username, u.phone, u.email, u.tags) AGAINST('${keyword}' IN NATURAL LANGUAGE MODE) as relevance_score
|
||
FROM users u
|
||
WHERE MATCH(u.username, u.phone, u.email, u.tags) AGAINST('${keyword}' IN NATURAL LANGUAGE MODE)
|
||
`
|
||
|
||
// 添加过滤条件
|
||
if (filters) {
|
||
Object.entries(filters).forEach(([key, value]) => {
|
||
query += ` AND u.${key} = '${value}'`
|
||
})
|
||
}
|
||
|
||
query += ` ORDER BY relevance_score DESC, u.last_active DESC`
|
||
query += ` LIMIT ${limit} OFFSET ${offset}`
|
||
|
||
return query
|
||
}
|
||
|
||
// 构建流量关键词搜索查询
|
||
private buildTrafficSearchQuery(request: SearchRequest): string {
|
||
const { keyword, filters, limit = 100, offset = 0 } = request
|
||
|
||
let query = `
|
||
SELECT
|
||
t.keyword_id,
|
||
t.keyword,
|
||
t.category,
|
||
t.search_volume,
|
||
t.competition,
|
||
t.cpc,
|
||
t.trend_data,
|
||
t.last_updated,
|
||
MATCH(t.keyword, t.category) AGAINST('${keyword}' IN NATURAL LANGUAGE MODE) as relevance_score
|
||
FROM traffic_keywords t
|
||
WHERE MATCH(t.keyword, t.category) AGAINST('${keyword}' IN NATURAL LANGUAGE MODE)
|
||
`
|
||
|
||
// 添加过滤条件
|
||
if (filters) {
|
||
Object.entries(filters).forEach(([key, value]) => {
|
||
query += ` AND t.${key} = '${value}'`
|
||
})
|
||
}
|
||
|
||
query += ` ORDER BY relevance_score DESC, t.search_volume DESC`
|
||
query += ` LIMIT ${limit} OFFSET ${offset}`
|
||
|
||
return query
|
||
}
|
||
|
||
// 构建统一搜索查询
|
||
private buildUnifiedSearchQuery(request: SearchRequest): string {
|
||
const { keyword, limit = 100, offset = 0 } = request
|
||
|
||
return `
|
||
(
|
||
SELECT
|
||
'user' as type,
|
||
user_id as id,
|
||
username as title,
|
||
CONCAT(phone, ' | ', email) as description,
|
||
tags,
|
||
last_active as updated_at,
|
||
MATCH(username, phone, email, tags) AGAINST('${keyword}' IN NATURAL LANGUAGE MODE) as relevance_score
|
||
FROM users
|
||
WHERE MATCH(username, phone, email, tags) AGAINST('${keyword}' IN NATURAL LANGUAGE MODE)
|
||
)
|
||
UNION ALL
|
||
(
|
||
SELECT
|
||
'traffic' as type,
|
||
keyword_id as id,
|
||
keyword as title,
|
||
CONCAT('搜索量: ', search_volume, ' | 竞争度: ', competition) as description,
|
||
category as tags,
|
||
last_updated as updated_at,
|
||
MATCH(keyword, category) AGAINST('${keyword}' IN NATURAL LANGUAGE MODE) as relevance_score
|
||
FROM traffic_keywords
|
||
WHERE MATCH(keyword, category) AGAINST('${keyword}' IN NATURAL LANGUAGE MODE)
|
||
)
|
||
ORDER BY relevance_score DESC
|
||
LIMIT ${limit} OFFSET ${offset}
|
||
`
|
||
}
|
||
|
||
// 用户数据分析 - 使用AI进行用户行为分析
|
||
async analyzeUserBehavior(userId: string): Promise<any> {
|
||
if (!this.connected) {
|
||
await this.connect()
|
||
}
|
||
|
||
try {
|
||
const query = `
|
||
SELECT
|
||
prediction,
|
||
confidence,
|
||
explanation
|
||
FROM mindsdb.user_behavior_predictor
|
||
WHERE user_id = '${userId}'
|
||
`
|
||
|
||
return await this.client.query(query)
|
||
} catch (error) {
|
||
console.error("用户行为分析失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 流量预测 - 使用AI预测流量趋势
|
||
async predictTrafficTrends(keyword: string, timeframe = "30d"): Promise<any> {
|
||
if (!this.connected) {
|
||
await this.connect()
|
||
}
|
||
|
||
try {
|
||
const query = `
|
||
SELECT
|
||
predicted_volume,
|
||
trend_direction,
|
||
confidence_interval,
|
||
factors
|
||
FROM mindsdb.traffic_predictor
|
||
WHERE keyword = '${keyword}' AND timeframe = '${timeframe}'
|
||
`
|
||
|
||
return await this.client.query(query)
|
||
} catch (error) {
|
||
console.error("流量预测失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 版本管理 - 创建数据版本
|
||
async createVersion(data: any, author: string, changes: string[]): Promise<VersionInfo> {
|
||
const version = `v${Date.now()}`
|
||
const timestamp = new Date().toISOString()
|
||
|
||
const versionInfo: VersionInfo = {
|
||
version,
|
||
timestamp,
|
||
changes,
|
||
author,
|
||
}
|
||
|
||
try {
|
||
// 存储版本信息
|
||
const query = `
|
||
INSERT INTO data_versions (version, timestamp, data_snapshot, changes, author)
|
||
VALUES ('${version}', '${timestamp}', '${JSON.stringify(data)}', '${JSON.stringify(changes)}', '${author}')
|
||
`
|
||
|
||
await this.client.query(query)
|
||
return versionInfo
|
||
} catch (error) {
|
||
console.error("创建版本失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 获取版本历史
|
||
async getVersionHistory(limit = 50): Promise<VersionInfo[]> {
|
||
if (!this.connected) {
|
||
await this.connect()
|
||
}
|
||
|
||
try {
|
||
const query = `
|
||
SELECT version, timestamp, changes, author
|
||
FROM data_versions
|
||
ORDER BY timestamp DESC
|
||
LIMIT ${limit}
|
||
`
|
||
|
||
const result = await this.client.query(query)
|
||
return result.rows || []
|
||
} catch (error) {
|
||
console.error("获取版本历史失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 恢复到指定版本
|
||
async restoreVersion(version: string): Promise<any> {
|
||
if (!this.connected) {
|
||
await this.connect()
|
||
}
|
||
|
||
try {
|
||
const query = `
|
||
SELECT data_snapshot
|
||
FROM data_versions
|
||
WHERE version = '${version}'
|
||
`
|
||
|
||
const result = await this.client.query(query)
|
||
if (result.rows && result.rows.length > 0) {
|
||
return JSON.parse(result.rows[0].data_snapshot)
|
||
}
|
||
|
||
throw new Error(`版本 ${version} 不存在`)
|
||
} catch (error) {
|
||
console.error("恢复版本失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 实时数据同步
|
||
async syncRealTimeData(source: string, data: any): Promise<void> {
|
||
if (!this.connected) {
|
||
await this.connect()
|
||
}
|
||
|
||
try {
|
||
const query = `
|
||
INSERT INTO real_time_data (source, data, timestamp)
|
||
VALUES ('${source}', '${JSON.stringify(data)}', NOW())
|
||
ON DUPLICATE KEY UPDATE
|
||
data = '${JSON.stringify(data)}',
|
||
timestamp = NOW()
|
||
`
|
||
|
||
await this.client.query(query)
|
||
} catch (error) {
|
||
console.error("实时数据同步失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
|
||
// 清理缓存
|
||
clearCache(): void {
|
||
this.cache.clear()
|
||
}
|
||
|
||
// 获取系统状态
|
||
async getSystemStatus(): Promise<any> {
|
||
if (!this.connected) {
|
||
await this.connect()
|
||
}
|
||
|
||
try {
|
||
const queries = [
|
||
"SELECT COUNT(*) as user_count FROM users",
|
||
"SELECT COUNT(*) as keyword_count FROM traffic_keywords",
|
||
"SELECT COUNT(*) as version_count FROM data_versions",
|
||
"SELECT AVG(response_time) as avg_response_time FROM query_logs WHERE created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)",
|
||
]
|
||
|
||
const results = await Promise.all(queries.map((query) => this.client.query(query)))
|
||
|
||
return {
|
||
userCount: results[0].rows[0].user_count,
|
||
keywordCount: results[1].rows[0].keyword_count,
|
||
versionCount: results[2].rows[0].version_count,
|
||
avgResponseTime: results[3].rows[0].avg_response_time || 0,
|
||
cacheSize: this.cache.size,
|
||
connected: this.connected,
|
||
}
|
||
} catch (error) {
|
||
console.error("获取系统状态失败:", error)
|
||
throw error
|
||
}
|
||
}
|
||
}
|
||
|
||
// 单例模式
|
||
let mindsDBInstance: MindsDBConnector | null = null
|
||
|
||
export function getMindsDBConnector(config?: MindsDBConfig): MindsDBConnector {
|
||
if (!mindsDBInstance && config) {
|
||
mindsDBInstance = new MindsDBConnector(config)
|
||
}
|
||
|
||
if (!mindsDBInstance) {
|
||
throw new Error("MindsDB连接器未初始化,请提供配置信息")
|
||
}
|
||
|
||
return mindsDBInstance
|
||
}
|