Activerecord Join 未返回所有预期结果
Activerecord Join not returning all expected results
我有一个我正在尝试查询的预先存在的 postgres 数据库。我已经建立了两个模型,客户和设备。我正在尝试查询两个 tables 使用非标准密钥加入它们。无论我尝试过什么,我只得到一个 table 的结果。我已经尝试更改 ActiveRecord 行为以使用非标准密钥以及 find_by_sql()。由于现有的 table 结构,我还禁用了默认的 table 复数形式。我是否漏掉了一些明显的东西?
ActiveRecord::Base.pluralize_table_names = false
class Customer < ActiveRecord::Base
self.primary_key = :acct
has_many :equipment, foreign_key: 'acct'
end
class Equipment < ActiveRecord::Base
self.primary_key = :acct
belongs_to :customer, foreign_key: 'acct'
end
me@nc:~/rails_workspace/pg_test$ rails c
Loading development environment (Rails 4.2.0.rc2)
2.2.1 :001 > Customer.first()
Customer Load (16.9ms) SELECT "customer".* FROM "customer" ORDER BY "customer"."acct" ASC LIMIT 1
=> #<Customer acct: "000002", franchise: "501", name: "NAME", address: "STREET ADDR", city: "CITY", state: "ST", zip: "ZIPCODE", phone: "1234567890", email: "email@domain.com", installdate: "2014-02-20", consumptiondate: nil, parent: "", sentoverage: false, exempt: false, pin: "", locked: false, status: "ACT">
2.2.1 :002 > Equipment.first()
Equipment Load (128.3ms) SELECT "equipment".* FROM "equipment" ORDER BY "equipment"."acct" ASC LIMIT 1
=> #<Equipment mac: "26225070", acct: "000002">
2.2.1 :003 >
2.2.1 :009 > Customer.find_by_sql("Select c.*, e.* from customer as c, equipment as e where e.acct = c.acct and c.acct = '000002' limit 1")
Customer Load (53.9ms) Select c.*, e.* from customer as c, equipment as e where e.acct = c.acct and c.acct = '000002' limit 1
=> [#<Customer acct: "000002", franchise: "501", name: "NAME", address: "STREET ADDR", city: "CITY", state: "ST", zip: "ZIPCODE", phone: "1234567890", email: "email@domain.com", installdate: "2014-02-20", consumptiondate: nil, parent: "", sentoverage: false, exempt: false, pin: "", locked: false, status: "ACT">]
2.2.1 :010 > Customer.joins('FULL OUTER JOIN equipment ON equipment.acct = customer.acct').limit(1)
Customer Load (119.9ms) SELECT "customer".* FROM "customer" FULL OUTER JOIN equipment ON equipment.acct = customer.acct LIMIT 1
=> #<ActiveRecord::Relation [#<Customer acct: "000002", franchise: "501", name: "NAME", address: "STREET ADDR", city: "CITY", state: "ST", zip: "ZIPCODE", phone: "1234567890", email: "email@domain.com", installdate: "2014-02-20", consumptiondate: nil, parent: "", sentoverage: false, exempt: false, pin: "", locked: false, status: "ACT">]>
2.2.1 :011 > Customer.joins(:equipment)
ActiveRecord::ConfigurationError: Association named 'equipment' was not found on Customer; perhaps you misspelled it?
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:218:in `find_reflection'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:223:in `block in build'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:222:in `each'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:222:in `map'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:222:in `build'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:99:in `initialize'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation/query_methods.rb:1039:in `new'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation/query_methods.rb:1039:in `build_joins'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation/query_methods.rb:863:in `build_arel'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation/query_methods.rb:855:in `arel'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation.rb:638:in `exec_queries'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation.rb:514:in `load'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation.rb:243:in `to_a'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation.rb:629:in `inspect'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands/console.rb:110:in `start'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands/console.rb:9:in `start'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands/commands_tasks.rb:68:in `console'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands.rb:17:in `<top (required)>'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:274:in `require'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:274:in `block in require'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:240:in `load_dependency'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:274:in `require'
from /home/me/rails_workspace/pg_test/bin/rails:8:in `<top (required)>'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:268:in `load'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:268:in `block in load'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:240:in `load_dependency'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:268:in `load'
from /home/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /home/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from -e:1:in `<main>'2.2.1 :012 >
编辑
修改了设备 class 将 belongs_to :equipments 更改为 :equipment。结果修复了 ActiveRecord::ConfigurationError: Association named 'equipment' 错误。但仍然没有解决加入问题。如果我使用客户table的"key"手动查询设备table,就会找到数据记录。
2.2.1 :008 > Customer.joins(:equipment).limit(1)
Customer Load (11.9ms) SELECT "customer".* FROM "customer" INNER JOIN "equipment" ON "equipment"."acct" = "customer"."acct" LIMIT 1
=> #<ActiveRecord::Relation > [#<Customer acct: "000002", franchise: "501", name: "NAME", address: "STREET ADDR", city: "CITY", state: "ST", zip: "ZIPCODE", phone: "1234567890", email: "email@domain.com", installdate: "2014-02-20", consumptiondate: nil, parent: "", sentoverage: false, exempt: false, pin: "", locked: false, status: "ACT">]
2.2.1 :017 > Equipment.where(acct: '000002')
Equipment Load (76.5ms) SELECT "equipment".* FROM "equipment" WHERE "equipment"."acct" = [["acct", "000002"]]
=> #<ActiveRecord::Relation [#<Equipment mac: "26225070", acct: "000002">, #<Equipment mac: "23126536", acct: "000002">, #<Equipment mac: "00E06F76A08A", acct: "000002">]>
我想我可能会看到你遗漏的东西。
Customer.joins(:anything)
将 return Customer
.
的集合
Equipment.joins(:anything)
将 return Equipment
.
的集合
也许你已经明白了,但也许还没有。
如果你想要一个混合了两者的结果集,我认为你必须从完全不同的角度来看待它,而且我认为我需要更好地理解你的意思最后为了能够提供任何好的建议。
编辑: 获取属于特定客户的设备:
Equipment.joins(:customer).where('customer.acct = ?', '000002')
为设备争取客户mac
:
Customer.joins(:equipment).where('equipment.mac = ?', '26225070')
为了更简单的解决方案,在 Equipment
模型中定义 scope
by_customer
,
class Equipment < ActiveRecord::Base
...
scope :by_customer,->(customer_conditions) { joins(:customer).where(customer: customer_conditions)}
end
并在 Customer
模型中跟随 scope
by_equipment
,
class Customer < ActiveRecord::Base
...
scope :by_equipment,->(equipment_conditions) { joins(:equipment).where(equipment: equipment_conditions)}
end
To find Equipments of Customer '000002'
@equipments = Equipment.by_customer(acct: '000002')
To find Customer who has an equipment of mac address is '26225070'
@customer = Customer.by_equipment(mac: '26225070')
我有一个我正在尝试查询的预先存在的 postgres 数据库。我已经建立了两个模型,客户和设备。我正在尝试查询两个 tables 使用非标准密钥加入它们。无论我尝试过什么,我只得到一个 table 的结果。我已经尝试更改 ActiveRecord 行为以使用非标准密钥以及 find_by_sql()。由于现有的 table 结构,我还禁用了默认的 table 复数形式。我是否漏掉了一些明显的东西?
ActiveRecord::Base.pluralize_table_names = false
class Customer < ActiveRecord::Base
self.primary_key = :acct
has_many :equipment, foreign_key: 'acct'
end
class Equipment < ActiveRecord::Base
self.primary_key = :acct
belongs_to :customer, foreign_key: 'acct'
end
me@nc:~/rails_workspace/pg_test$ rails c
Loading development environment (Rails 4.2.0.rc2)
2.2.1 :001 > Customer.first()
Customer Load (16.9ms) SELECT "customer".* FROM "customer" ORDER BY "customer"."acct" ASC LIMIT 1
=> #<Customer acct: "000002", franchise: "501", name: "NAME", address: "STREET ADDR", city: "CITY", state: "ST", zip: "ZIPCODE", phone: "1234567890", email: "email@domain.com", installdate: "2014-02-20", consumptiondate: nil, parent: "", sentoverage: false, exempt: false, pin: "", locked: false, status: "ACT">
2.2.1 :002 > Equipment.first()
Equipment Load (128.3ms) SELECT "equipment".* FROM "equipment" ORDER BY "equipment"."acct" ASC LIMIT 1
=> #<Equipment mac: "26225070", acct: "000002">
2.2.1 :003 >
2.2.1 :009 > Customer.find_by_sql("Select c.*, e.* from customer as c, equipment as e where e.acct = c.acct and c.acct = '000002' limit 1")
Customer Load (53.9ms) Select c.*, e.* from customer as c, equipment as e where e.acct = c.acct and c.acct = '000002' limit 1
=> [#<Customer acct: "000002", franchise: "501", name: "NAME", address: "STREET ADDR", city: "CITY", state: "ST", zip: "ZIPCODE", phone: "1234567890", email: "email@domain.com", installdate: "2014-02-20", consumptiondate: nil, parent: "", sentoverage: false, exempt: false, pin: "", locked: false, status: "ACT">]
2.2.1 :010 > Customer.joins('FULL OUTER JOIN equipment ON equipment.acct = customer.acct').limit(1)
Customer Load (119.9ms) SELECT "customer".* FROM "customer" FULL OUTER JOIN equipment ON equipment.acct = customer.acct LIMIT 1
=> #<ActiveRecord::Relation [#<Customer acct: "000002", franchise: "501", name: "NAME", address: "STREET ADDR", city: "CITY", state: "ST", zip: "ZIPCODE", phone: "1234567890", email: "email@domain.com", installdate: "2014-02-20", consumptiondate: nil, parent: "", sentoverage: false, exempt: false, pin: "", locked: false, status: "ACT">]>
2.2.1 :011 > Customer.joins(:equipment)
ActiveRecord::ConfigurationError: Association named 'equipment' was not found on Customer; perhaps you misspelled it?
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:218:in `find_reflection'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:223:in `block in build'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:222:in `each'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:222:in `map'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:222:in `build'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/associations/join_dependency.rb:99:in `initialize'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation/query_methods.rb:1039:in `new'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation/query_methods.rb:1039:in `build_joins'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation/query_methods.rb:863:in `build_arel'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation/query_methods.rb:855:in `arel'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation.rb:638:in `exec_queries'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation.rb:514:in `load'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation.rb:243:in `to_a'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activerecord-4.2.0.rc2/lib/active_record/relation.rb:629:in `inspect'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands/console.rb:110:in `start'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands/console.rb:9:in `start'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands/commands_tasks.rb:68:in `console'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/railties-4.2.0.rc2/lib/rails/commands.rb:17:in `<top (required)>'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:274:in `require'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:274:in `block in require'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:240:in `load_dependency'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:274:in `require'
from /home/me/rails_workspace/pg_test/bin/rails:8:in `<top (required)>'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:268:in `load'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:268:in `block in load'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:240:in `load_dependency'
from /home/me/.rvm/gems/ruby-2.2.1@pg_test/gems/activesupport-4.2.0.rc2/lib/active_support/dependencies.rb:268:in `load'
from /home/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /home/me/.rvm/rubies/ruby-2.2.1/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from -e:1:in `<main>'2.2.1 :012 >
编辑
修改了设备 class 将 belongs_to :equipments 更改为 :equipment。结果修复了 ActiveRecord::ConfigurationError: Association named 'equipment' 错误。但仍然没有解决加入问题。如果我使用客户table的"key"手动查询设备table,就会找到数据记录。
2.2.1 :008 > Customer.joins(:equipment).limit(1)
Customer Load (11.9ms) SELECT "customer".* FROM "customer" INNER JOIN "equipment" ON "equipment"."acct" = "customer"."acct" LIMIT 1
=> #<ActiveRecord::Relation > [#<Customer acct: "000002", franchise: "501", name: "NAME", address: "STREET ADDR", city: "CITY", state: "ST", zip: "ZIPCODE", phone: "1234567890", email: "email@domain.com", installdate: "2014-02-20", consumptiondate: nil, parent: "", sentoverage: false, exempt: false, pin: "", locked: false, status: "ACT">]
2.2.1 :017 > Equipment.where(acct: '000002')
Equipment Load (76.5ms) SELECT "equipment".* FROM "equipment" WHERE "equipment"."acct" = [["acct", "000002"]]
=> #<ActiveRecord::Relation [#<Equipment mac: "26225070", acct: "000002">, #<Equipment mac: "23126536", acct: "000002">, #<Equipment mac: "00E06F76A08A", acct: "000002">]>
我想我可能会看到你遗漏的东西。
Customer.joins(:anything)
将 return Customer
.
Equipment.joins(:anything)
将 return Equipment
.
也许你已经明白了,但也许还没有。
如果你想要一个混合了两者的结果集,我认为你必须从完全不同的角度来看待它,而且我认为我需要更好地理解你的意思最后为了能够提供任何好的建议。
编辑: 获取属于特定客户的设备:
Equipment.joins(:customer).where('customer.acct = ?', '000002')
为设备争取客户mac
:
Customer.joins(:equipment).where('equipment.mac = ?', '26225070')
为了更简单的解决方案,在 Equipment
模型中定义 scope
by_customer
,
class Equipment < ActiveRecord::Base
...
scope :by_customer,->(customer_conditions) { joins(:customer).where(customer: customer_conditions)}
end
并在 Customer
模型中跟随 scope
by_equipment
,
class Customer < ActiveRecord::Base
...
scope :by_equipment,->(equipment_conditions) { joins(:equipment).where(equipment: equipment_conditions)}
end
To find Equipments of Customer '000002'
@equipments = Equipment.by_customer(acct: '000002')
To find Customer who has an equipment of mac address is '26225070'
@customer = Customer.by_equipment(mac: '26225070')