1

我正在尝试对生成的模型字符串进行搜索,该字符串由 has_one 关联形成。这是我的模型:

街道.rb

class Street < ActiveRecord::Base
  has_many :houses
  validates :street_type, presence: true
  validates :name, presence: true, uniqueness: {:scope => :street_type, :case_sensitive => false }
  def text
    street_type + " " + name
  end
end

房子.rb

class House < ActiveRecord::Base
  belongs_to :street
  has_many :apartments
  validates :street_id, presence: true
  validates :number, presence: true
  def text
    street.text + ", " + number
  end
end

公寓.rb

class Apartment < ActiveRecord::Base
  belongs_to :house
  has_one :street, through => :house
  has_many :accounts
  validates :house_id, presence: true
  validates :number, presence: true, uniqueness: {:scope => :house_id, :case_sensitive => false}
  def text
    house.text + ", ap. " + number
  end
end

账户.rb

class Account < ActiveRecord::Base
  belongs_to :appartment
  has_one :house, :through => :appartment
  belongs_to :resident
  validates :appartment_id, presence: true
  validates :resident_id, presence: true, uniqueness: {:scope => :appartment_id, :case_sensitive => false}
  def text
    uniq_id + " (" + appartment.text + ")"
  end
end

我必须通过匹配一些地址字符串来搜索所有帐户。我不知道该怎么做。

  • 示例第一个帐户文本“123-1123-122(Regent street, 51, ap. 3)”
  • 示例第二个帐户文本“123-1123-155 (Regent street, 51, ap. 6)”
  • 示例搜索文本“Regent street, 51”

有人可以帮助我了解如何做到这一点吗?

4

3 回答 3

3

搜索连接的字段

您正在搜索Account#text,在 DB 中找不到它,除非您将它存储在那里(请参阅“搜索完整的 Apartment#text”),(从代码判断)似乎并非如此。您不能在 ActiveRecord 查询中使用模型方法的返回值。因此,首先您需要从搜索字符串中解析街道类型和名称、门牌号和公寓号。

假设您知道街道类型和名称、门牌号和公寓号,您应该(减去错误,我实际上并没有测试)能够通过以下方式找到帐户

Account.
  joins(:apartment => { :house => :street }).
  where('apartment.number' => apt_num,
        'apartment.house.number' => house_num,
        'apartment.house.street.name' => street_name,
        'apartment.house.street.street_type' => street_type)

您的地址信息是高度结构化的。它可能好也可能不好。在不知道任何细节的情况下,我建议您检查结合全文搜索的结构化或非结构化地址信息(纯文本字段)是否适合您。

有关 AR 查询的更多信息,请参阅http://guides.rubyonrails.org/active_record_querying.html

搜索完整的公寓#text

如果您不想从生成的公寓文本字段中解析名称和数字,则需要将其存储在 db.xml 中。您可以通过挂钩before_save和更新文本字段(让它被称为cached_text)来包含Apartment#text.

class Apartment < ActiveRecord::Base
  before_save :update_cached_text
  def update_cached_text
    self.cached_text = text
  end
end

Apartment#cached_text如果您更改门牌号或街道名称或类型,现在当然会不同步。为了保持同步,您需要在#touch每次保存房屋或街道时“重新保存”(参见 )所有关联的公寓。

现在您可以使用完整搜索Apartment#text

Account.
  joins(:apartment).
  where('apartment.cached_text' => text)

或者它的一个子串

Account.
  joins(:apartment).
  where("apartment.cached_text LIKE '%?%'", text)
于 2013-09-05T08:29:18.910 回答
1
your_result = Account.includes(:apartment, :apartment => :house, :apartment => {:house => :street}).where(:apartment => {:number => ...}).where(:house => {:number => ...}).where(:street => {:name => ...})
于 2013-09-05T08:29:04.093 回答
1

尝试以下

Account.includes([:appartment => [:house => :street]]).where("CONCAT('accounts.uniq_id', ' (', 'streets.street_type', ' ', 'streets.name', ' ', 'houses.number', ', ap. ', 'houses.number', ')') like '%?%'", your_search_text)
于 2013-09-05T08:21:12.807 回答