在GoLand中为SQLite数据库内的唯一用户实现带作者数组的专属Feed方案咨询
在GoLand中为SQLite数据库内的唯一用户实现带作者数组的专属Feed方案咨询
嘿,兄弟,我太懂你现在的困惑了——SQLite确实不支持原生数组类型,但咱们完全可以用关系型数据库的标准玩法来解决这个问题,不用纠结数组那事儿!
首先得调整一下你的表结构,因为原来的feed表存authors整数的思路走不通,没法同时存多个作者和对应的isFave状态。咱们换个方式,用关联表来实现这个需求,这是处理这类一对多/多对多场景的常规操作:
调整后的表结构
用户表(user):保留你原来的设计就行,用户和Feed是一对一的关系,所以可以直接用用户ID关联Feed:
CREATE TABLE user ( id INTEGER PRIMARY KEY AUTOINCREMENT, phone TEXT UNIQUE NOT NULL, feed_id INTEGER UNIQUE NOT NULL, FOREIGN KEY (feed_id) REFERENCES feed(id) );(如果确定每个用户对应唯一Feed,其实
feed_id可以直接和user.id一致,这样连外键都能简化)Feed表(feed):不用再存作者数组了,只保留基础标识就行:
CREATE TABLE feed ( id INTEGER PRIMARY KEY AUTOINCREMENT -- 以后如果需要给Feed加其他属性,比如创建时间,直接加字段就行 );Feed-作者关联表(feed_author):这是核心!用来关联Feed和作者,同时存储每个作者在该Feed中的
isFave状态:CREATE TABLE feed_author ( feed_id INTEGER NOT NULL, author_id INTEGER NOT NULL, is_fave BOOLEAN NOT NULL DEFAULT 0, PRIMARY KEY (feed_id, author_id), -- 确保同一个Feed里每个作者只出现一次 FOREIGN KEY (feed_id) REFERENCES feed(id), FOREIGN KEY (author_id) REFERENCES author(id) );作者表(author):继续保留你的原设计:
CREATE TABLE author ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL );
为什么这么设计?
每个用户对应一个专属Feed(一对一),每个Feed可以关联N个作者(一对多),而且每个作者在这个Feed里有独立的“是否收藏”状态——这个关联表完美承载了这些信息,比数组灵活多了,还能保证数据的规范性。
Go代码里怎么用?
假设你用GORM(Go里常用的ORM框架,在GoLand里也很好用),先定义对应的结构体:
package main import "gorm.io/gorm" type User struct { ID int `gorm:"primaryKey"` Phone string `gorm:"unique;not null"` FeedID int `gorm:"unique;not null"` Feed Feed `gorm:"foreignKey:FeedID"` } type Feed struct { ID int `gorm:"primaryKey"` FeedAuthors []FeedAuthor `gorm:"foreignKey:FeedID"` } type FeedAuthor struct { FeedID int `gorm:"primaryKey"` AuthorID int `gorm:"primaryKey"` IsFave bool `gorm:"not null;default:false"` Author Author `gorm:"foreignKey:AuthorID"` } type Author struct { ID int `gorm:"primaryKey"` Name string `gorm:"not null"` }
然后查询某个用户的专属Feed和作者列表(带收藏状态):
// 假设已经初始化了db连接 var user User // 预加载关联数据,一次性查出来 db.Preload("Feed.FeedAuthors.Author").First(&user, 1) // 1是目标用户ID // 遍历输出结果 for _, fa := range user.Feed.FeedAuthors { println("作者:", fa.Author.Name, "是否收藏:", fa.IsFave) }
如果用原生SQL的话,查询语句大概是这样:
SELECT a.id, a.name, fa.is_fave FROM user u JOIN feed f ON u.feed_id = f.id JOIN feed_author fa ON f.id = fa.feed_id JOIN author a ON fa.author_id = a.id WHERE u.id = ?; -- 替换成目标用户ID
小提示
- SQLite默认是关闭外键约束的,你得在连接数据库的时候开启:连接字符串加上
_foreign_keys=on,比如:sqlite:///your_database.db?_foreign_keys=on,这样能保证数据的完整性,避免出现无效的关联。 - 如果以后Feed需要加其他属性(比如更新时间、分类),直接在
feed表加字段就行,扩展性很强。
备注:内容来源于stack exchange,提问作者Denis Popkov




