Commit 41522997 authored by Wade's avatar Wade

update qa table

parent 2349111b
...@@ -27,11 +27,6 @@ type Input struct { ...@@ -27,11 +27,6 @@ type Input struct {
} }
func main() { func main() {
mainQA()
ctx := context.Background() ctx := context.Background()
......
...@@ -48,13 +48,13 @@ func (mr *ModelRouter) GetModel(modelName, apiKey string) (ai.Model, error) { ...@@ -48,13 +48,13 @@ func (mr *ModelRouter) GetModel(modelName, apiKey string) (ai.Model, error) {
return model, nil return model, nil
} }
type Input struct { // type Input struct {
Content []*ai.Part `json:"content,omitempty"` // Content []*ai.Part `json:"content,omitempty"`
Model string `json:"model,omitempty"` // Model string `json:"model,omitempty"`
APIKey string `json:"apiKey,omitempty"` // APIKey string `json:"apiKey,omitempty"`
Username string `json:"username,omitempty"` // Username string `json:"username,omitempty"`
UserID string `json:"user_id,omitempty"` // UserID string `json:"user_id,omitempty"`
} // }
func defineChatFlow(g *genkit.Genkit, mr *ModelRouter) { func defineChatFlow(g *genkit.Genkit, mr *ModelRouter) {
......
create table public.qa ( create table public.qa (
id bigint generated by default as identity not null, id bigint generated by default as identity not null,
created_at timestamp with time zone not null default now(), created_at timestamp with time zone not null default now(),
user_id bigint null,
username text null,
question text null, question text null,
answer text null, answer text null,
summary text null,
"from" text null,
"to" text null,
from_id text null,
to_id text null,
constraint qa_pkey primary key (id) constraint qa_pkey primary key (id)
) TABLESPACE pg_default; ) TABLESPACE pg_default;
CREATE VIEW public.qa_latest_from_id AS
SELECT DISTINCT ON (qa.from_id)
qa.id,
qa.created_at,
qa.question,
qa.answer,
qa.summary,
qa."from",
qa."to",
qa.from_id,
qa.to_id
FROM
qa
WHERE
qa.from_id IS NOT NULL
ORDER BY
qa.from_id,
qa.created_at DESC;
create view public.latest_qa as
select distinct
on (qa.user_id) qa.id,
qa.created_at,
qa.user_id,
qa.username,
qa.question,
qa.answer
from
qa
order by
qa.user_id,
qa.created_at desc;
\ No newline at end of file
...@@ -5,74 +5,89 @@ import ( ...@@ -5,74 +5,89 @@ import (
"database/sql" "database/sql"
"flag" "flag"
"fmt" "fmt"
"log"
"time" "time"
_ "github.com/lib/pq" _ "github.com/lib/pq"
) )
var ( var (
connString = flag.String("dbconn", "", "database connection string") connString = flag.String("dbconn", "", "database connection string")
) )
type QA struct { type QA struct {
ID int64 // 主键 ID int64 // 主键
CreatedAt time.Time // 创建时间 CreatedAt time.Time // 创建时间
UserID *int64 // 可空的用户 ID FromID *string // 可空的 from_id
Username *string // 可空的用户名 From *string // 可空的 from
Question *string // 可空的问题 Question *string // 可空的问题
Answer *string // 可空的答案 Answer *string // 可空的答案
Summary *string // 可空的摘要 Summary *string // 可空的摘要
To *string // 可空的 to
ToID *string // 可空的 to_id
} }
// QAStore 定义 DAO 接口 // QAStore 定义 DAO 接口
type QAStore interface { type QAStore interface {
// GetLatestQA 从 latest_qa 视图读取指定 user_id 的最新记录 // GetLatestQA 从 qa_latest_from_id 视图读取指定 from_id 的最新记录
GetLatestQA(ctx context.Context, userID *int64) ([]QA, error) GetLatestQA(ctx context.Context, fromID *string) ([]QA, error)
// WriteQA 插入或更新 qa 表记录 // WriteQA 插入或更新 qa 表记录
WriteQA(ctx context.Context, qa QA) (int64, error) WriteQA(ctx context.Context, qa QA) (int64, error)
} }
// qaStore 是 QAStore 接口的实现 // qaStore 是 QAStore 接口的实现
type qaStore struct { type qaStore struct {
db *sql.DB db *sql.DB
} }
// NewQAStore 创建新的 QAStore 实例 // NewQAStore 创建新的 QAStore 实例
func NewQAStore(db *sql.DB) QAStore { func NewQAStore(db *sql.DB) QAStore {
return &qaStore{db: db} return &qaStore{db: db}
} }
func (s *qaStore) GetLatestQA(ctx context.Context, userID *int64) ([]QA, error) { // 初始化数据库连接并返回 QAStore
func InitQAStore() (QAStore, error) {
// Supabase 提供的连接字符串
connString := "postgresql://postgres.awcfgdodiuqnlsobcivq:P99IU9NEoDRPsBfb@aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres"
// 打开数据库连接
db, err := sql.Open("postgres", connString)
if err != nil {
return nil, fmt.Errorf("open database: %w", err)
}
// 测试数据库连接
if err := db.Ping(); err != nil {
db.Close()
return nil, fmt.Errorf("ping database: %w", err)
}
// 返回 QAStore 实例
return NewQAStore(db), nil
}
func (s *qaStore) GetLatestQA(ctx context.Context, fromID *string) ([]QA, error) {
query := ` query := `
SELECT id, created_at, user_id, username, question, answer, summary SELECT id, created_at, question, answer, summary, "from", "to", from_id, to_id
FROM latest_qa FROM qa_latest_from_id
WHERE user_id = $1 OR (user_id IS NULL AND $1 IS NULL)` WHERE from_id = $1 OR (from_id IS NULL AND $1 IS NULL)`
args := []interface{}{userID} args := []interface{}{fromID}
if userID == nil { if fromID == nil {
args = []interface{}{nil} args = []interface{}{nil}
} }
rows, err := s.db.QueryContext(ctx, query, args...) rows, err := s.db.QueryContext(ctx, query, args...)
if err != nil { if err != nil {
return nil, fmt.Errorf("query latest_qa: %w", err) return nil, fmt.Errorf("query qa_latest_from_id: %w", err)
} }
defer rows.Close() defer rows.Close()
var results []QA var results []QA
for rows.Next() { for rows.Next() {
var qa QA var qa QA
var userIDVal sql.NullInt64 var question, answer, summary, from, to, fromIDVal, toIDVal sql.NullString
var username, question, answer, summary sql.NullString if err := rows.Scan(&qa.ID, &qa.CreatedAt, &question, &answer, &summary, &from, &to, &fromIDVal, &toIDVal); err != nil {
if err := rows.Scan(&qa.ID, &qa.CreatedAt, &userIDVal, &username, &question, &answer, &summary); err != nil {
return nil, fmt.Errorf("scan row: %w", err) return nil, fmt.Errorf("scan row: %w", err)
} }
if userIDVal.Valid {
qa.UserID = &userIDVal.Int64
}
if username.Valid {
qa.Username = &username.String
}
if question.Valid { if question.Valid {
qa.Question = &question.String qa.Question = &question.String
} }
...@@ -82,6 +97,18 @@ func (s *qaStore) GetLatestQA(ctx context.Context, userID *int64) ([]QA, error) ...@@ -82,6 +97,18 @@ func (s *qaStore) GetLatestQA(ctx context.Context, userID *int64) ([]QA, error)
if summary.Valid { if summary.Valid {
qa.Summary = &summary.String qa.Summary = &summary.String
} }
if from.Valid {
qa.From = &from.String
}
if to.Valid {
qa.To = &to.String
}
if fromIDVal.Valid {
qa.FromID = &fromIDVal.String
}
if toIDVal.Valid {
qa.ToID = &toIDVal.String
}
results = append(results, qa) results = append(results, qa)
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {
...@@ -95,11 +122,20 @@ func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) { ...@@ -95,11 +122,20 @@ func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) {
// 更新记录 // 更新记录
query := ` query := `
UPDATE qa UPDATE qa
SET user_id = $1, username = $2, question = $3, answer = $4, summary = $5 SET question = $1, answer = $2, summary = $3, "from" = $4, "to" = $5, from_id = $6, to_id = $7
WHERE id = $6 WHERE id = $8
RETURNING id` RETURNING id`
var updatedID int64 var updatedID int64
err := s.db.QueryRowContext(ctx, query, qa.UserID, qa.Username, qa.Question, qa.Answer, qa.Summary, qa.ID).Scan(&updatedID) err := s.db.QueryRowContext(ctx, query,
derefString(qa.Question),
derefString(qa.Answer),
derefString(qa.Summary),
derefString(qa.From),
derefString(qa.To),
derefString(qa.FromID),
derefString(qa.ToID),
qa.ID,
).Scan(&updatedID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return 0, fmt.Errorf("no record found with id %d", qa.ID) return 0, fmt.Errorf("no record found with id %d", qa.ID)
} }
...@@ -111,97 +147,33 @@ func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) { ...@@ -111,97 +147,33 @@ func (s *qaStore) WriteQA(ctx context.Context, qa QA) (int64, error) {
// 插入新记录 // 插入新记录
query := ` query := `
INSERT INTO qa (user_id, username, question, answer, summary) INSERT INTO qa (question, answer, summary, "from", "to", from_id, to_id)
VALUES ($1, $2, $3, $4, $5) VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING id` RETURNING id`
var newID int64 var newID int64
err := s.db.QueryRowContext(ctx, query, qa.UserID, qa.Username, qa.Question, qa.Answer, qa.Summary).Scan(&newID) err := s.db.QueryRowContext(ctx, query,
derefString(qa.Question),
derefString(qa.Answer),
derefString(qa.Summary),
derefString(qa.From),
derefString(qa.To),
derefString(qa.FromID),
derefString(qa.ToID),
).Scan(&newID)
if err != nil { if err != nil {
return 0, fmt.Errorf("insert qa: %w", err) return 0, fmt.Errorf("insert qa: %w", err)
} }
return newID, nil return newID, nil
} }
func mainQA() {
// postgres://postgres.awcfgdodiuqnlsobcivq:[YOUR-PASSWORD]@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres
// postgres://postgres.awcfgdodiuqnlsobcivq:rNVrqxaapXypEGg8@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres
//connString := "postgres://postgres.awcfgdodiuqnlsobcivq:rNVrqxaapXypEGg8@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres"
// var connString = "postgres://postgres.awcfgdodiuqnlsobcivq:rNVrqxaapXypEGg8@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres"
var connString = "postgresql://postgres.awcfgdodiuqnlsobcivq:P8L00j7k3wHRwUJw@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres"
db, err := sql.Open("postgres", connString)
if err != nil {
log.Fatalf("open database: %v", err)
}
defer db.Close()
store := NewQAStore(db)
ctx := context.Background()
// 示例:读取 user_id=101 的最新 QA
results, err := store.GetLatestQA(ctx, int64Ptr(101))
if err != nil {
log.Fatalf("get latest QA: %v", err)
}
for _, qa := range results {
fmt.Printf("ID: %d, CreatedAt: %v, UserID: %v, Username: %v, Question: %v, Answer: %v, Summary: %v\n",
qa.ID, qa.CreatedAt, derefInt64(qa.UserID), derefString(qa.Username),
derefString(qa.Question), derefString(qa.Answer), derefString(qa.Summary))
}
// 示例:插入新 QA
newQA := QA{
UserID: int64Ptr(101),
Username: stringPtr("alice"),
Question: stringPtr("What is AI?"),
Answer: stringPtr("AI is..."),
Summary: stringPtr("AI overview"),
}
newID, err := store.WriteQA(ctx, newQA)
if err != nil {
log.Fatalf("write QA: %v", err)
}
fmt.Printf("Inserted QA with ID: %d\n", newID)
// 示例:更新 QA
updateQA := QA{
ID: newID,
UserID: int64Ptr(101),
Username: stringPtr("alice_updated"),
Question: stringPtr("What is NLP?"),
Answer: stringPtr("NLP is..."),
Summary: stringPtr("NLP overview"),
}
updatedID, err := store.WriteQA(ctx, updateQA)
if err != nil {
log.Fatalf("update QA: %v", err)
}
fmt.Printf("Updated QA with ID: %d\n", updatedID)
}
// 辅助函数:处理指针类型的空值 // 辅助函数:处理指针类型的空值
func int64Ptr(i int64) *int64 {
return &i
}
func stringPtr(s string) *string { func stringPtr(s string) *string {
return &s return &s
}
func derefInt64(p *int64) interface{} {
if p == nil {
return nil
}
return *p
} }
func derefString(p *string) interface{} { func derefString(p *string) interface{} {
if p == nil { if p == nil {
return nil return nil
} }
return *p return *p
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment