【问题标题】:Efficient database design for a college notes application大学笔记应用程序的高效数据库设计
【发布时间】:2019-10-21 23:57:44
【问题描述】:

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

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

术语/我的设计: “Note”可以是“Ebook”、“Question Paper”、“Practical File”、“Note”类型。注释将有标题、描述和文件附件。注释将属于一个主题和类别。

类别:如“电子书”、“试卷”等。它会有一个标题。

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

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

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

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

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,其中包含“分支”、“学期”和“主题”作为过滤笔记的选择。

【问题讨论】:

    标签: ruby-on-rails database-design


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      在这种情况下为什么不直接获取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 %>
      

      查看Russian Doll Caching 了解更多信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-03
        • 2016-12-04
        • 1970-01-01
        • 1970-01-01
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多