You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

在GoLand中为SQLite数据库内的唯一用户实现带作者数组的专属Feed方案咨询

在GoLand中为SQLite数据库内的唯一用户实现带作者数组的专属Feed方案咨询

嘿,兄弟,我太懂你现在的困惑了——SQLite确实不支持原生数组类型,但咱们完全可以用关系型数据库的标准玩法来解决这个问题,不用纠结数组那事儿!

首先得调整一下你的表结构,因为原来的feed表存authors整数的思路走不通,没法同时存多个作者和对应的isFave状态。咱们换个方式,用关联表来实现这个需求,这是处理这类一对多/多对多场景的常规操作:

调整后的表结构

  1. 用户表(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一致,这样连外键都能简化)

  2. Feed表(feed):不用再存作者数组了,只保留基础标识就行:

    CREATE TABLE feed (
        id INTEGER PRIMARY KEY AUTOINCREMENT
        -- 以后如果需要给Feed加其他属性,比如创建时间,直接加字段就行
    );
    
  3. 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)
    );
    
  4. 作者表(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

火山引擎 最新活动