5

我有一个 Rails ActiveRecord 查询,可以找到名称为某个标记的所有记录。

records = Market.where("lower(name) = ?", name.downcase );
rec = records.first;
count = records.count;

服务器显示调用.first.count都在访问数据库。

←[1m←[35mCACHE (0.0ms)←[0m  SELECT "markets".* FROM "markets" WHERE (lower(nam
e) = 'my market') LIMIT 1

←[1m←[36mCACHE (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM "markets" WHERE (lower(na
me) = 'my market')←[0m

为什么它可以使用已经查询的结果时去数据库获取计数?

我担心未来的表现。今天有1000条记录。当该表包含 800 万行时,执行两次查询,一次查询数据,一次查询计数,这将是昂贵的。

如何从集合而不是数据库中获取计数?

4

3 回答 3

10

RactiveRecord 使用惰性查询从数据库中获取数据。如果你想简单地统计记录,你只能调用重新运行数组的大小。

records = Market.where("lower(name) = ?", name.downcase ).all
records.size
于 2012-06-01T03:05:50.410 回答
8

所以,records是一个ActiveRelation. 您会认为这是符合您标准的所有市场记录的数组where,但事实并非如此。每次您引用类似firstcount关于该关系的内容时,它都会执行查询以检索您所要求的内容。

要将实际记录放入数组中,只需添加.all到关系中即可实际检索它们。喜欢:

records = Market.where("lower(name) = ?", name.downcase).all
count = records.count
于 2012-06-01T03:08:38.343 回答
2

对于 Rails 6.0.1 和 Ruby 2.6.5

您需要使用to_a.

records = Market.where("lower(name) = ?", name.downcase).to_a

这将创建 SQL 查询并将结果存储在数组中records

然后,当您调用其中一个时,它只会返回数据或进行计算,而不是重新运行查询records.firstrecords.count这对于records.size和是一样的records.length

另一个例子

我需要为我正在开发的博客这样做。我试图运行查询以查找与帖子关联的所有标签,并且我想计算有多少标签。在我遇到to_a 后缀之前,这会导致多次查询。

因此,我的 SQL 查询如下所示:

@tags = TagMap.where(post_id: @post).joins(:tag).select(:id, '"tags"."name"').to_a

这会在我的 TagMap 表中查找与我正在查看的帖子post_id相同的所有记录。id然后它连接到标签表并从标签表中只提取idTagMap 记录和标签名称。然后它将它们全部放入一个数组中。然后我可以运行@tags.count,它将返回该帖子的 TagMap 记录数,而无需进行其他查询。

我希望这可以帮助任何使用 Rails 6+ 的人

于 2019-12-01T23:14:27.423 回答