133 lines
4.1 KiB
Python
133 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
数据库迁移脚本:创建 news_articles 表
|
||
|
||
使用方法:
|
||
python scripts/migrate_create_news_table.py
|
||
|
||
或者在服务器上直接执行 SQL(参考 schema.sql)
|
||
"""
|
||
import sqlite3
|
||
import os
|
||
from pathlib import Path
|
||
|
||
|
||
# SQL 建表语句
|
||
CREATE_TABLE_SQL = """
|
||
CREATE TABLE IF NOT EXISTS news_articles (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
title VARCHAR(500) NOT NULL,
|
||
content TEXT,
|
||
content_hash VARCHAR(64) NOT NULL,
|
||
url VARCHAR(1000) NOT NULL UNIQUE,
|
||
source VARCHAR(100) NOT NULL,
|
||
author VARCHAR(200),
|
||
category VARCHAR(50) NOT NULL,
|
||
tags JSON,
|
||
published_at DATETIME,
|
||
crawled_at DATETIME NOT NULL,
|
||
llm_analyzed BOOLEAN DEFAULT 0,
|
||
market_impact VARCHAR(20),
|
||
impact_type VARCHAR(50),
|
||
relevant_symbols JSON,
|
||
sentiment VARCHAR(20),
|
||
summary TEXT,
|
||
key_points JSON,
|
||
trading_advice TEXT,
|
||
priority REAL DEFAULT 0.0,
|
||
priority_reason TEXT,
|
||
notified BOOLEAN DEFAULT 0,
|
||
notification_sent_at DATETIME,
|
||
notification_channel VARCHAR(50),
|
||
quality_score REAL,
|
||
duplicate_of INTEGER,
|
||
is_active BOOLEAN DEFAULT 1,
|
||
created_at DATETIME NOT NULL,
|
||
updated_at DATETIME NOT NULL
|
||
);
|
||
|
||
-- 创建索引
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_content_hash ON news_articles(content_hash);
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_category ON news_articles(category);
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_published_at ON news_articles(published_at);
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_crawled_at ON news_articles(crawled_at);
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_llm_analyzed ON news_articles(llm_analyzed);
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_priority ON news_articles(priority);
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_notified ON news_articles(notified);
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_is_active ON news_articles(is_active);
|
||
CREATE INDEX IF NOT EXISTS idx_news_articles_created_at ON news_articles(created_at);
|
||
"""
|
||
|
||
|
||
def migrate_create_news_table():
|
||
"""创建 news_articles 表"""
|
||
|
||
# 数据库路径
|
||
db_path = Path(__file__).parent.parent / "backend" / "stock_agent.db"
|
||
|
||
if not db_path.exists():
|
||
print(f"❌ 数据库文件不存在: {db_path}")
|
||
return False
|
||
|
||
try:
|
||
# 连接数据库
|
||
conn = sqlite3.connect(str(db_path))
|
||
cursor = conn.cursor()
|
||
|
||
# 检查表是否已存在
|
||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='news_articles'")
|
||
if cursor.fetchone():
|
||
print("✅ news_articles 表已存在,无需迁移")
|
||
conn.close()
|
||
return True
|
||
|
||
# 创建表
|
||
print(f"📝 正在创建 news_articles 表到 {db_path}...")
|
||
|
||
# 执行 SQL
|
||
for sql_statement in CREATE_TABLE_SQL.split(';'):
|
||
sql_statement = sql_statement.strip()
|
||
if sql_statement:
|
||
cursor.execute(sql_statement)
|
||
|
||
conn.commit()
|
||
|
||
# 验证
|
||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='news_articles'")
|
||
if cursor.fetchone():
|
||
print("✅ news_articles 表创建成功")
|
||
|
||
# 显示索引
|
||
cursor.execute("SELECT name FROM sqlite_master WHERE type='index' AND name LIKE 'idx_news_articles%'")
|
||
indexes = cursor.fetchall()
|
||
print(f"✅ 创建了 {len(indexes)} 个索引")
|
||
|
||
conn.close()
|
||
return True
|
||
else:
|
||
print("❌ 表创建失败")
|
||
conn.close()
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"❌ 迁移失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
|
||
if __name__ == "__main__":
|
||
print("=" * 60)
|
||
print("数据库迁移:创建 news_articles 表")
|
||
print("=" * 60)
|
||
|
||
success = migrate_create_news_table()
|
||
|
||
if success:
|
||
print("\n✅ 迁移完成!")
|
||
print("\n请重启服务以使更改生效:")
|
||
print(" pm2 restart stock-agent")
|
||
else:
|
||
print("\n❌ 迁移失败!")
|
||
print("\n如果自动迁移失败,可以参考 scripts/schema_news.sql 手动执行 SQL")
|