# 数据库模型文档 ## 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) ### 基本用法 ```javascript 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长度 ### 去重逻辑 #### 创建时去重 ```javascript // 创建书签时会自动检查是否已存在相同URL const exists = await db("bookmarks").where({ user_id: userId, url: url }).first() if (exists) { throw new Error("该用户下已存在相同 URL 的书签") } ``` #### 更新时去重 ```javascript // 更新时会检查新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` - 每次更新时自动设置为当前时间 ### 错误处理 所有方法都包含适当的错误处理: ```javascript 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表 ### 运行迁移 ```bash # 运行迁移 npx knex migrate:latest ``` ### 使用场景 #### 个人书签管理 ```javascript // 用户登录后查看自己的书签 const myBookmarks = await BookmarkModel.findAllByUser(currentUserId) ``` #### 书签同步 ```javascript // 支持多设备书签同步 const bookmarks = await BookmarkModel.findAllByUser(userId) // 可以导出为JSON或其他格式 ``` #### 书签分享 ```javascript // 可以扩展实现书签分享功能 // 通过添加 share_status 字段实现 ``` ### 扩展建议 可以考虑添加以下功能: - 书签分类和标签 - 书签收藏夹 - 书签导入/导出 - 书签搜索功能 - 书签访问统计 - 书签分享功能 - 书签同步功能 - 书签备份和恢复 ### 安全注意事项 1. **用户隔离**: 确保用户只能访问自己的书签 2. **URL验证**: 在应用层验证URL的有效性 3. **输入清理**: 对用户输入进行适当的清理和验证 4. **权限控制**: 实现适当的访问控制机制