You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4.6 KiB

数据库模型文档

BookmarkModel

BookmarkModel 是一个书签管理模型,提供了用户书签的CRUD操作和查询方法,支持URL去重和用户隔离。

主要特性

  • 完整的CRUD操作
  • 用户隔离的书签管理
  • URL去重验证
  • 自动时间戳管理
  • 外键关联用户表

数据库字段

字段名 类型 说明
id integer 主键,自增
user_id integer 用户ID(外键,关联users表)
title string(200) 书签标题(必填,最大长度200)
url string(500) 书签URL
description text 书签描述
created_at timestamp 创建时间
updated_at timestamp 更新时间

外键关系

  • user_id 关联 users.id
  • 删除用户时,相关书签会自动删除(CASCADE)

基本用法

import { BookmarkModel } from '../models/BookmarkModel.js'

// 创建书签
const bookmark = await BookmarkModel.create({
    user_id: 1,
    title: "GitHub - 开源代码托管平台",
    url: "https://github.com",
    description: "全球最大的代码托管平台"
})

// 查找用户的所有书签
const userBookmarks = await BookmarkModel.findAllByUser(1)

// 根据ID查找书签
const bookmark = await BookmarkModel.findById(1)

// 更新书签
await BookmarkModel.update(1, {
    title: "GitHub - 更新后的标题",
    description: "更新后的描述"
})

// 删除书签
await BookmarkModel.delete(1)

// 查找用户特定URL的书签
const bookmark = await BookmarkModel.findByUserAndUrl(1, "https://github.com")

查询方法

基础查询

  • findAllByUser(userId) - 查找指定用户的所有书签(按ID降序)
  • findById(id) - 根据ID查找书签
  • findByUserAndUrl(userId, url) - 查找用户特定URL的书签

数据操作

  • create(data) - 创建新书签
  • update(id, data) - 更新书签信息
  • delete(id) - 删除书签

数据验证和约束

必填字段

  • user_id - 用户ID不能为空
  • title - 标题不能为空

唯一性约束

  • 同一用户下不能存在相同URL的书签
  • 系统会自动检查并阻止重复URL的创建

URL处理

  • URL会自动去除首尾空格
  • 支持最大500字符的URL长度

去重逻辑

创建时去重

// 创建书签时会自动检查是否已存在相同URL
const exists = await db("bookmarks").where({ 
    user_id: userId, 
    url: url 
}).first()

if (exists) {
    throw new Error("该用户下已存在相同 URL 的书签")
}

更新时去重

// 更新时会检查新URL是否与其他书签冲突(排除自身)
const exists = await db("bookmarks")
    .where({ user_id: nextUserId, url: nextUrl })
    .andWhereNot({ id })
    .first()

if (exists) {
    throw new Error("该用户下已存在相同 URL 的书签")
}

时间戳管理

系统自动管理以下时间戳:

  • created_at - 创建时自动设置为当前时间
  • updated_at - 每次更新时自动设置为当前时间

错误处理

所有方法都包含适当的错误处理:

try {
    const bookmark = await BookmarkModel.create({
        user_id: 1,
        title: "重复的书签",
        url: "https://example.com" // 如果已存在会抛出错误
    })
} catch (error) {
    console.error("创建书签失败:", error.message)
}

性能优化

  • user_id 字段已添加索引,提高查询性能
  • 支持按用户ID快速查询书签列表

迁移和种子

项目包含完整的数据库迁移文件:

  • 20250830015422_create_bookmarks_table.mjs - 创建bookmarks表

运行迁移

# 运行迁移
npx knex migrate:latest

使用场景

个人书签管理

// 用户登录后查看自己的书签
const myBookmarks = await BookmarkModel.findAllByUser(currentUserId)

书签同步

// 支持多设备书签同步
const bookmarks = await BookmarkModel.findAllByUser(userId)
// 可以导出为JSON或其他格式

书签分享

// 可以扩展实现书签分享功能
// 通过添加 share_status 字段实现

扩展建议

可以考虑添加以下功能:

  • 书签分类和标签
  • 书签收藏夹
  • 书签导入/导出
  • 书签搜索功能
  • 书签访问统计
  • 书签分享功能
  • 书签同步功能
  • 书签备份和恢复

安全注意事项

  1. 用户隔离: 确保用户只能访问自己的书签
  2. URL验证: 在应用层验证URL的有效性
  3. 输入清理: 对用户输入进行适当的清理和验证
  4. 权限控制: 实现适当的访问控制机制