Ruby on rails Rails:为什么Pulk方法返回uniq值?

Ruby on rails Rails:为什么Pulk方法返回uniq值?,ruby-on-rails,Ruby On Rails,我有一个帐户模型,其中有一列角色。 我想通过在日期创建的来选择不同的角色(例如2018年1月1日创建的所有不同角色等),并仅获取列角色的值。 选择不同的角色可以很好地作为一个查询,但是当涉及到获取值时,我会得到意想不到的结果 如果我只是对所有查询结果使用map函数,那么一切正常,SQL查询看起来也不错 Account.where(id: 1..10).select(:created_at, :role).distinct.map(&:role) Account Load (1.0ms)

我有一个
帐户
模型,其中有一列
角色
。 我想通过在日期创建的
来选择不同的角色(例如2018年1月1日创建的所有不同角色等),并仅获取列
角色
的值。 选择不同的角色可以很好地作为一个查询,但是当涉及到获取值时,我会得到意想不到的结果

如果我只是对所有查询结果使用
map
函数,那么一切正常,SQL查询看起来也不错

Account.where(id: 1..10).select(:created_at, :role).distinct.map(&:role)
Account Load (1.0ms)  SELECT DISTINCT "accounts"."created_at", "accounts"."role" FROM "accounts" WHERE ("accounts"."id" BETWEEN $1 AND $2)  [["id", 1], ["id", 10]]
=> ["admin", "manager", "manager", "manager", "manager", "manager", "manager", "manager", "manager"]
但是,如果我想将
.map(&:role)
更改为
.pulk(:role)
,这在定义上是相同的,
pulk
方法首先删除
distinct
条件,只保留
distinct
按角色,正如我们在查询开始时看到的那样

Account.where(id: 1..10).select(:created_at, :role).distinct.pluck(:role)
(0.7ms)  SELECT DISTINCT "accounts"."role" FROM "accounts" WHERE ("accounts"."id" BETWEEN $1 AND $2)  [["id", 1], ["id", 10]]
=> ["admin", "manager"]
在编写的
pulk
文档中,只有当代码看起来像
.pulk('distinct role')


为什么我的情况是这样?这是一些未记录的功能吗

对于你的问题“为什么在我的情况下它是这样工作的?”的简短回答是因为它应该是这样工作的。你说:

在Pull文档中。这样写的话,只有当代码看起来像
.pull('distinct role')

这是不准确的。您引用的文档显示了这样一个示例,作为使用
DISTINCT
进行提取的一种方法,但没有说明这是应用
DISTINCT
SQL修饰符的唯一方法。由于已将
.distinct
添加到
ActiveRecord
关系中,因此生成的查询将是
选择distinct
。这会提示SQL为您提供唯一的值,而不是
pull
方法
Pull
只返回DB给它的确切内容

对于在
处创建的和角色的不同组合使用Pull后实现目标的方法,您可以使用组:

Account.where(id: 1..10).group(:created_at, :role).pluck(:role)
# => SELECT "accounts"."role" FROM "accounts" WHERE ("accounts"."id" BETWEEN $1 AND $2) GROUP BY "accounts"."created_at", "accounts"."role"  [["id", 1], ["id", 10]]

.group(:created_at,:role)
调用(添加一个
group BY
SQL子句)将根据
created_at
role
为您提供唯一的行组合(如果同一
role
与多个
created_at
值关联,则该
角色可能会多次出现)。然后,
.pull(:role)
将只获取
角色的值

我不明白为什么需要使用select,您可以使用
where
pull
获取和筛选数据,而
where
优于
select
,因为
select
数据库
中获取了您指定的所有数据,并对它们进行迭代,以在ruby级别过滤数据,但使用
where
可在
数据库
级别过滤掉这些数据。使用pull时,请删除select,你会得到同样的结果。在使用Pulk时,AR似乎以任何方式改进了查询以添加特定属性,这种方式如果将foo和bar传递给Pulk,您将得到不同的model.foo,model.bar。注意:如果您使用AR,并且需要作为结果的数组,您不需要映射,它可以工作,但这是Pulk的场景。使用
时,选择(:created_at,:role).distinct
它通过这两个属性进行distinct,在任何情况下,如果添加PULLC,它将覆盖第一个distinct并使用PULLC方法中指定的属性。请记住,如果以那种方式使用Pull,您不需要选择。where.select(:created_at,:role)。distinct.pull(:role)
=
where.distinct.pull(:role)
“将.map(&:role)更改为.pull(:role),它们定义相同”-noop,它们不相同,甚至不相近<代码>映射是一种通用转换
Pulk
是ActiveRecord查询生成器中的一个修饰符。哦,关于
分组依据的评论真好!我通过使用
map
解决了我的问题,但是
groupby
在速度方面看起来更合适。