繁体   English   中英

Rails 和 Postgres:在数组上连接表

[英]Rails & Postgres: Join tables on an array

从概念上讲,我想做的是能够说:产品 a 有 5 种颜色可供选择,这将是一组颜色 ID。 这些颜色 ID 是链接到颜色表的键,颜色表包含颜色相关数据,例如十六进制表示、彩色图像等。 最后,我想将颜色表与产品表连接起来,以便提取与颜色相关的数据。

在我当前的设置中,我有两个表: productscolors 在我的products表中,我有一列 ( color_ids ),其中包含一个整数数组。 该数组保存colors表中colors的 ID。 为了在 Rails 中加入这两者,我在Product类中创建了一个自定义 SQL 字符串,例如:

class Product < ApplicationRecord
  has_many :colors

  def self.custom_query   
    "SELECT * FROM products JOIN colors on colors.id = ANY(products.color_ids)
    WHERE products.name = 'Some Product'"
  end

end

我尝试使用关联( includes(:colors) ),但这似乎不起作用,因为主 ID 是一个 ID 数组。

有没有更优雅/ Rails 的方式来实现我想要做的事情?

使用简单的has_and_belongs_to_many关联。 不要将您的参考 ID 存储在数组中,仅仅因为 PostgreSQL 允许您这样做,这不是关系数据库中应该如何实现关系。

# new migration
create_table :colors_products do |t|
  t.references :color, foreign_key: true
  t.references :product, foreign_key: true
end
add_index :colors_products, [:color_id, :product_id], unique: true


class Product < ApplicationRecord
  has_and_belongs_to_many :colors
end

class Color < ApplicationRecord
  has_and_belongs_to_many :products
end

所有的 ActiveRecord 方法都将起作用。

为什么不应该与数组建立关系(除非您真的知道自己在做什么):

  1. 您不能使用外键。 您将能够在您的数组中拥有一个不再在数据库中的 color_id。
  2. 如果您删除一种颜色,您的数据库将无法自动清除所有产品的 ID。
  3. ActiveRecord(和大多数 ORM)根本不起作用,您将需要大量的解决方法。

你可以简单地做

class Product < ApplicationRecord
  def colors   
    Color.where(id: color_ids)
  end
end

class Color < ApplicationRecord
  def products   
    Product.where('? = Any (category_ids)', id)
  end
end

您可以创建一个名为如下的视图:

CREATE VIEW product_colors(id, product_id, name, hex, image) AS

SELECT
  p.id as product_id,
  c.name,
  c.hex,
  c.image
FROM
  (
  SELECT
      id,
      unnest(color_ids) as color_id
    FROM
      products
  ) as p
  INNER JOIN colors c
    ON c.id = p.color_id;

然后添加模型ProductColor

def readonly?
 true
end

您可以将此视图视为子模型。 Products.includes(:product_colors)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM