【问题标题】:Rails has_many based on a json array columnRails has_many 基于 json 数组列
【发布时间】:2020-09-05 05:22:40
【问题描述】:

是否可以告诉 Rails 使用 JSON 列作为关系的“后端”? 我有一个 Article 模型,它将评论 ID 存储在 JSON 列 Article#comment_ids

class Article < ApplicationRecord
  def comments
    Comment.where(id: comment_ids)
  end
end

class Comment < ApplicationRecord
end

Article.first.comment_ids
=> [1,2]

Article.first.comments
=> [#<Comment:0x00007f4d7cff7c08 id: 1>,#<Comment:0x00007f4d7cff7c08 id: 2>]

有什么办法可以替换这段代码

def comments
  Comment.where(id: comment_ids)
end

有一个

has_many :comments # somehow reference #comment_ids

背景:我的应用程序的其他部分使用预加载和article.association(:comments).loaded? 之类的东西。而且因为它不是 rails 关系,所以这不适用于 cmets 关系。

【问题讨论】:

标签: mysql ruby-on-rails mysql-json


【解决方案1】:

不,这是不可能的。 ActiveRecord 是围绕关系模型构建的,其中的表与其他表相关。查询 JSON/JSONB/Array 列需要使用完全不同的运算符,它们不是多语言的。与传统的连接表相比,它们也几乎没有优势:

  • JSON/Array 列不能用作外键。所以数据库不能保证参照完整性。
  • 连接表可以有一个高效的复合索引,而您可以在 JSON/数组列上使用 GIN 索引,但您仍然必须遍历整个事物才能连接另一个表。
  • 您在单个列中放置多个值违反了First normal form (1NF)
  • 带有 JSON/array 列的查询将是可怕的和不可读的。连接的速度也比您想象的要快。

【讨论】:

  • 我们在使用连接表时遇到了很大的问题,模型本身有大约 2500 万条记录和 1-100 个相关模型。因此插入和更新连接表通常会导致锁定等待超时。将它们作为 json 数组存储在记录本身中使我们能够更快地执行更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
相关资源
最近更新 更多