Ruby on rails 如何通过列使rails查询唯一

Ruby on rails 如何通过列使rails查询唯一,ruby-on-rails,postgresql,Ruby On Rails,Postgresql,我有一个公司模型,它有许多披露。披露中有名为标题、pdf和pdf\u-sha256的列 class Company < ActiveRecord::Base has_many :disclosures end class Disclosure < ActiveRecord::Base belongs_to :company end 如何使用Rails查询获得相同的结果 Model.select(:rating) 其结果是一个模型对象数组。不是简单的评级。从uniq的角度

我有一个
公司
模型,它有许多
披露
披露
中有名为
标题
pdf
pdf\u-sha256
的列

class Company < ActiveRecord::Base
  has_many :disclosures
end

class Disclosure < ActiveRecord::Base
  belongs_to :company
end
如何使用Rails查询获得相同的结果

Model.select(:rating)
其结果是一个模型对象数组。不是简单的评级。从uniq的角度来看,他们完全不同。您可以使用以下选项:

Model.select(:rating).map(&:rating).uniq
或者这个(效率最高)

更新

显然,从rails 5.0.0.1开始,它只适用于“顶级”查询,如上所述。不适用于集合代理(例如,“has_many”关系)

在这种情况下,请在查询后执行重复数据消除

user.addresses.pluck(:city).uniq # => ['Moscow']
为什么不:

ids = Disclosure.select(:id, :pdf_sha256).distinct.map(&:id)
Disclosure.find(ids)

由于id是主键,因此无论哪种方式,它都是不同的,所以您所要做的就是映射id并按id查找披露内容。

您可以使用uniq方法实现这一点

 Company.first.disclosures.to_a.uniq(&:pdf_sha256)
这将向您返回uniq通过cloumn“pdf_sha256”发布的披露记录


希望这对你有帮助!干杯

如果您需要与distinct
pdf\u sha256
建立关系,并且不需要明确的条件,您可以使用-

scope :unique_pdf_sha256, -> { where.not(pdf_sha256: nil).group(:pdf_sha256) }
scope :nil_pdf_sha256,    -> { where(pdf_sha256: nil) }
您可以使用
,但传递给它的关系必须在结构上兼容。因此,即使在这两个作用域中得到相同类型的关系,也不能将其与
一起使用


编辑:为了使它在结构上相互兼容,您可以在一个查询中看到@AlexSantos的

,首先可以为每个不同的
pdf\u sha256
子查询获取不同的
id
,然后在查询中,通过传递子查询获取该ID集中的元素,如下所示:

def unique_disclosures_by_pdf_sha256(company)
  subquery = company.disclosures.select('MIN(id) as id').group(:pdf_sha256)
  company.disclosures.where(id: subquery)
    .or(company.disclosures.where(pdf_sha256: nil))
end
最棒的是ActiveRecord是延迟加载的,因此第一个
子查询将不会运行,而是会合并到第二个主查询中,以便在数据库中创建单个查询。然后,它将检索所有由
pdf\u sha256
唯一的
披露
以及所有将
pdf\u sha256
设置为
nil
的披露

如果您好奇,给定一家公司,结果查询将类似于:

SELECT  "disclosures".* FROM "disclosures" 
WHERE (
  "disclosures"."company_id" = $1 AND "disclosures"."id" IN (
    SELECT MAX(id) as id FROM "disclosures" WHERE "disclosures"."company_id" = $2 GROUP BY "disclosures"."pdf_sha256"
  ) 
  OR "disclosures"."company_id" = $3 AND "disclosures"."pdf_sha256" IS NULL
)
这个解决方案的好处在于,返回的值是ActiveRecord查询,因此在实际需要之前不会加载它。您还可以使用它来保持链接查询。例如,您可以仅选择
id
而不是整个模型,并限制数据库返回的结果数:

unique_disclosures_by_pdf_sha256(company).select(:id).limit(10).each { |d| puts d }

假设您使用的是Rails 5,您可以链接一个.or命令来合并这两个查询

pdf_sha256_unique_disclosures = company.disclosures.where(pdf_sha256: nil).or(company.disclosures.where.not(pdf_sha256: nil))
然后你可以按照逻辑继续你的小组

但是,在上面的示例中,我不确定目标是什么,但我很想更好地了解如何使用生成的
companys
变量

如果您想拥有包含nil的唯一pdf_sha256密钥的散列,以及由此产生的唯一披露文档,您可以尝试以下操作:

sorted_disclosures = company.disclosures.group_by(&:pdf_sha256).each_with_object({}) do |entries, hash|
  hash[entries[0]] = entries[1].max_by{|v| v.title.length}
end

这将为您提供一个类似于组的哈希结构,其中您的密钥都是唯一的pdf sha256,并且该值将是与该pdf sha256匹配的最长命名披露。

在您的示例中,我希望获得
地址的所有列,不仅是
city
列。我想让
disposition
模型的所有列都通过
pdf\u sha256
ActiveRecord::QueryMethods\uniq
的唯一性进行过滤,它只是
ActiveRecord::QueryMethods\distinct
的别名。因此,该方法在这种情况下不起作用。我想你把
数组#uniq
弄混了。您的代码使用
to a
方法,如
company.disclosures.to a.uniq(&:pdf\u sha256)
。谢谢@ironsand。我已经编辑了我的答案。希望这对你有帮助。请按照我回答的这个链接。。如果我无法执行
MAX(id)
,因为我有UUID值id-s,我该怎么办。我尝试了
select('MAX(created_at)as created_at')。group(:feed_type)
,但我仍然需要ID-s进行下一次查询并按ID-s搜索记录。
unique_disclosures_by_pdf_sha256(company).select(:id).limit(10).each { |d| puts d }
pdf_sha256_unique_disclosures = company.disclosures.where(pdf_sha256: nil).or(company.disclosures.where.not(pdf_sha256: nil))
sorted_disclosures = company.disclosures.group_by(&:pdf_sha256).each_with_object({}) do |entries, hash|
  hash[entries[0]] = entries[1].max_by{|v| v.title.length}
end