feat: refactor data asset center for enhanced search and analytics
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>
This commit is contained in:
433
lib/mindsdb-connector.ts
Normal file
433
lib/mindsdb-connector.ts
Normal file
@@ -0,0 +1,433 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user