Rails/transak作用域为具有条件的多个子行返回一个父行



我使用rails(5.2.4.3(、transak和postgres,并使用以下简化的数据库模式:

Buildings
- id
BuildingSegments
- id
- building_id
- name

多个建筑段可以属于一个建筑,但一个建筑也可以有0个建筑段。我的数据库中大约有800万栋建筑和1000万个建筑段。

我正在尝试创建两个查询/作用域,它们也可以被链接:

  1. 返回所有没有建筑段且具有任何提供ID的建筑。我正试图将其纳入一个类似的范围:Building.without_building_segments([1, 2])。因此,这可以返回一个没有任何建筑段的建筑,或者有n个建筑段,其中没有一个建筑段的id为1或2。

  2. 返回每个提供的ID至少有一个建筑段的所有建筑。类似的作用域:Building.with_building_segments([1, 2])。因此,这只能返回具有至少两个建筑段的建筑的建筑,其中一个建筑段id为1,另一个为2。

我尝试过使用各种联接、事务谓词和子查询,但都没有成功。

你将如何解决这个问题?

所以这里的要点是您想要使用一些可搜索的作用域。基本上,这些只是你让洗劫意识到的常规作用域。

class Building < ActiveRecord
# A set of ransackable scopes.
#https://activerecord-hackery.github.io/ransack/going-further/other-notes/#using-scopesclass-methods
# @param [Object] auth_object Auth object from Ransack/Devise
# @return [Array] An array of scopes that are class methods.
def self.ransackable_scopes(auth_object = nil)
%i(without_building_segments with_building_segments)
end
# Scope to only get buildings without segments.
# @return [ActiveRecord::Relation]
def self.without_building_segments
includes(:building_segments).where(building_segments: { id: nil })
end
# Scope to only get buildings with segments of ids
# @param [Array] ids array of building segment ids
# @return [ActiveRecord::Relation]
def self.with_building_segments(ids)
includes(:building_segments).where(building_segments: { id: ids })
end
end
Building.ransack({ without_building_segments: true })
# => Building without any segments
Building.ransack({ with_building_segments: [1,2] })
# => Buildings that have segments of 1 and 2

最新更新