大学笔记应用程序的高效数据库设计



我正在设计一个Web应用程序,用于存储不同的大学材料,如笔记,电子书,试卷。

要求: 1.根据分支和学期获取笔记列表,例如如果选择了"计算机科学工程"和学期1,则获取该分支和学期的所有笔记。 2. 根据学期和分支获取所有科目。

术语/我设计的内容: "笔记"可以是"电子书"、"试卷"、"实用文件"、"笔记"类型。注释将具有标题,说明和文件附件。注释将属于一个主题和类别。

类别:如"电子书","试卷"等。它将有一个标题。

分支:它表示研究领域,如"计算机科学与工程","电气工程"等。它将有一个标题。一个分支将有多个学期。

主题:它将有一个标题。如"数据结构"、"机器学习"等。

学期:表示通常的大学学期。一个学期将有多个科目。不同的学期可以共享科目。就像计算机科学工程第一学期的科目可能在电气工程的第三学分中一样。

以下是我目前制作的模型。

class Note < ApplicationRecord
belongs_to :user
belongs_to :category
belongs_to :subject
end
class Category < ApplicationRecord
has_many :notes
end
class Branch < ApplicationRecord
has_many :semesters
end
class Semester < ApplicationRecord
has_and_belongs_to_many :subjects
belongs_to :branch
end
class Subject < ApplicationRecord
has_and_belongs_to_many :semesters
has_many :notes
end

架构文件

create_table "branches", force: :cascade do |t|
t.string "title"
t.string "short_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "categories", force: :cascade do |t|
t.string "title"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "notes", force: :cascade do |t|
t.text "title"
t.text "description"
t.integer "user_id"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "subject_id"
t.index ["category_id"], name: "index_notes_on_category_id"
t.index ["subject_id"], name: "index_notes_on_subject_id"
t.index ["user_id"], name: "index_notes_on_user_id"
end
create_table "semesters", force: :cascade do |t|
t.integer "branch_id"
t.string "title"
t.integer "semester"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["branch_id"], name: "index_semesters_on_branch_id"
end
create_table "semesters_subjects", id: false, force: :cascade do |t|
t.integer "subject_id", null: false
t.integer "semester_id", null: false
t.index ["semester_id", "subject_id"], name: "index_semesters_subjects_on_semester_id_and_subject_id"
t.index ["subject_id", "semester_id"], name: "index_semesters_subjects_on_subject_id_and_semester_id"
end
create_table "subjects", force: :cascade do |t|
t.string "title"
t.string "short_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

目前,我正在使用这样的分支和学期获得科目:

@subjects = Subject.joins(:semesters).where("semester_id = ? AND branch_id = ?", params[:semester], params[:branch]).pluck(:title, :id)

我觉得这可以改进,因为我会加入所有请求。我最终想要的是创建一个过滤器 UI,其中包含"分支"、"学期"和"主题"作为筛选笔记的选择。

我认为你的设计很好,你可以尝试使用一个scope_method,这将简化过滤,甚至使用类方法:

scope :branch_semester, -> {joins(:semesters).where("semester_id = ? AND 
branch_id = ?", params[:semester], params[:branch]).pluck(:title, :id)}

在这种情况下,为什么不直接获取Branch

@subjects = Branch.find(params[:branch]).subjects

分支和学期是一对一的,因此如果您有分支 ID,则不需要主题 ID。 请注意,我要求subjectsBranch

为此,只需使用has_many :through

class Branch < ApplicationRecord
has_many :semesters
has_many :subjects, through: :semesters
end

我认为你的设计很好,它是标准的关系数据库的东西。如果你真的想使用连接,你可以使用某种元数据,比如某个表中的 JSON 列,但在这种情况下,IMO 是矫枉过正的。

过早优化是万恶之源。如果您正在缓存,则也无需担心。

因为你的控制器,而不是要求.subjects,它可以只返回分支:

@branch = Branch.find(params[:branch])

然后在你看来

<% cache @branch do %>
... use @branch.subjects here, it will only be called once when generating the cache
<% end %>

查看 俄罗斯娃娃缓存 了解更多信息。

最新更新