Ruby on rails Rails:为什么(id:objects)在哪里工作?
我有以下声明:Ruby on rails Rails:为什么(id:objects)在哪里工作?,ruby-on-rails,Ruby On Rails,我有以下声明: Customer.where(city_id: cities) SELECT customers.* FROM customers WHERE customers.city_id IN (SELECT cities.id FROM cities... 这将导致以下SQL语句: Customer.where(city_id: cities) SELECT customers.* FROM customers WHERE customers.city_id IN (SELECT
Customer.where(city_id: cities)
SELECT customers.* FROM customers WHERE customers.city_id IN (SELECT cities.id FROM cities...
这将导致以下SQL语句:
Customer.where(city_id: cities)
SELECT customers.* FROM customers WHERE customers.city_id IN (SELECT cities.id FROM cities...
这是故意的行为吗?它在什么地方有记录吗?我不会使用上面的Rails代码,而是使用以下代码之一:
Customer.where(city_id: cities.pluck(:id))
或
这将产生完全相同的SQL语句
它为什么有效
ActiveRecord查询生成器中的某些深层信息非常聪明,可以看出,如果传递数组或查询/条件,它需要构建in子句
这有文件记录吗
对
2.3.3子集条件
如果要使用IN表达式查找记录,可以将数组传递给条件散列:
Client.where(orders_count: [1,3,5])
此代码将生成如下所示的SQL:
SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
AREL查询库允许您以快捷方式传入ActiveRecord对象。然后,它会将它们的主键属性传递到它用来联系数据库的SQL中 在查找多个对象时,AREL库将尝试在尽可能少的数据库往返中查找信息。它通过将正在进行的查询作为一组条件保留,直到检索对象为止,来实现这一点 这种方式效率低下:
users = User.where(age: 30).all
# ^^^ get all these users from the database
memberships = Membership.where(user_id: users)
# ^^^^^ This will pass in each of the ids as a condition
users = User.where(age: 30)
# This is still a query object, it hasn't asked the database for the users yet.
memberships = Membership.where(user_id: users)
# Note: this line is the same, but users is an AREL query, not an array of users
基本上,这种方式将发出两条SQL语句:
select * from users where age = 30;
select * from memberships where user_id in (1, 2, 3);
其中每一项都涉及到应用程序之间对网络端口的调用,然后通过同一端口传回数据
这将更有效率:
users = User.where(age: 30).all
# ^^^ get all these users from the database
memberships = Membership.where(user_id: users)
# ^^^^^ This will pass in each of the ids as a condition
users = User.where(age: 30)
# This is still a query object, it hasn't asked the database for the users yet.
memberships = Membership.where(user_id: users)
# Note: this line is the same, but users is an AREL query, not an array of users
相反,它将构建一个嵌套的查询,因此它只需往返数据库一次
select * from memberships
where user_id in (
select id from users where age = 30
);
所以,是的,这是预期的行为。这是Rails的一点魔力,它旨在提高应用程序的性能,而不必知道它是如何工作的
还有一些很酷的优化,比如如果你调用first或last而不是all,它将只检索一条记录
User.where(name: 'bob').all
# SELECT "USERS".* FROM "USERS" WHERE "USERS"."NAME" = 'bob'
User.where(name: 'bob').first
# SELECT "USERS".* FROM "USERS" WHERE "USERS"."NAME" = 'bob' AND ROWNUM <= 1
或者,如果您设置了一个顺序,并调用last,它将颠倒顺序,然后只获取列表中的最后一条,而不是获取所有记录并只提供最后一条
User.where(name: 'bob').order(:login).first
# SELECT * FROM (SELECT "USERS".* FROM "USERS" WHERE "USERS"."NAME" = 'bob' ORDER BY login) WHERE ROWNUM <= 1
User.where(name: 'bob').order(:login).first
# SELECT * FROM (SELECT "USERS".* FROM "USERS" WHERE "USERS"."NAME" = 'bob' ORDER BY login DESC) WHERE ROWNUM <= 1
# Notice, login DESC
使用整数数组转换为IN语句是有意义的,但为什么这也适用于对象?如果cities主键不是id而是其他东西怎么办?@0lli.rocks:在大多数情况下,当您将AR对象传递到查询生成器中时,它将被缩减为其id主键。与Project.finduser类似:u将导致从用户id=123的项目中选择*from。ActiveRecord有很多像这样有用的魔法。