我最近听说在Postgres中可以更快地查询显着的一些many-to-many
和one-to-many
关系(没有额外的连接数据,例如用户会员组)使用id的数组列而不是连接表see discussion for Node Postgres ORM。
对于many-to-many
关系,选择维护关系数组的哪个表(或两者)将取决于查询的方向(用户< - >组将需要两个表上的数组列,用户 - &gt ; tag只需要在users表的数组列中维护关系。
几个问题:
many-to-many
关系中,是否有人有比较简单连接表与数组列的基准? ```
module ArrayRelationships
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
# association must be lower case, pluralized name of associated class
def array_has_many(association)
define_method(association) do
instance_name = association.singularize
class_name = instance_name.titleize
class_name.constantize.where(id: self.send("#{instance_name}_ids"))
end
end
end
end
class User << ActiveRecord::Base
include ArrayRelationships
array_has_many :tags
end
当然,users表必须在数据库中包含:tag_ids
数组字段。如果我们想为Tag#用户添加反向关系,我们只需添加db字段,包括ArrayRelationships和array_has_many :users
。
答案 0 :(得分:1)
我还没有尝试过,但似乎有人构建了一个gem来支持关联数组:https://github.com/marshall-lee/has_array_of。从README中复制:
假设我们有一个包含许多视频的播放列表。一个视频可以包含在许多播放列表中。这是一个经典的多对多情况,但我们以不同的方式实现它。
# db/migrate/20141027125227_create_playlist.rb
class CreatePlaylist < ActiveRecord::Migration
def change
create_table :playlists do |t|
t.integer :video_ids, array: true # adding array fields works only starting from Rails 4
t.index :video_ids, using: :gin # we add GIN index to speed up specific queries on array
end
end
end
# app/models/playlist.rb
class Playlist < ActiveRecord::Base
has_array_of :videos # by convention, it assumes that Post has a video_ids array field
end
# app/models/video.rb
class Video < ActiveRecord::Base
belongs_to_array_in_many :playlists # optional
end
现在我们可以像常规数组一样使用videos
。它会正确代理video_ids
字段的所有更改。
playlist = Playlist.find(1)
playlist.videos = [video1,video2] # playlist.video_ids = [1, 2]
playlist.videos[0] = video3 # playlist.video_ids[0] = 3
playlist.videos.insert(1, video4) # playlist.video_ids = [3, 4, 2]
playlist.videos.delete_at(1) # playlist.video_ids = [3, 2]
playlist.videos.pop # playlist.video_ids = [3]
# ... and so on
video3.playlists
# => [playlist]