【问题标题】:Search object by generated string by has_one associations通过 has_one 关联生成的字符串搜索对象
【发布时间】:2013-09-08 22:49:45
【问题描述】:

我正在尝试对生成的模型字符串进行搜索,该字符串由 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”

有人可以帮我理解怎么做吗?

【问题讨论】:

    标签: ruby-on-rails search ruby-on-rails-4


    【解决方案1】:

    搜索连接字段

    您正在搜索 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)
    

    【讨论】:

    • 错了!我没有单独的这个字段,我必须按定义的字符串过滤。
    • 我不确定我是否理解。你指的“这个字段”和“定义的字符串”是什么?如果有帮助,我会写出我在回答中提到的第一个选项。
    【解决方案2】:

    尝试以下

    Account.includes([:appartment => [:house => :street]]).where("CONCAT('accounts.uniq_id', ' (', 'streets.street_type', ' ', 'streets.name', ' ', 'houses.number', ', ap. ', 'houses.number', ')') like '%?%'", your_search_text)
    

    【讨论】:

    • appartments.text 也是生成的字符串。你确定这段代码就够了吗?
    • @KirillWarp,我已经编辑了我的答案。我没有测试过,只是检查一下,现在这样,你可以找到结果。您可能需要更改查询中的某些内容。
    【解决方案3】:
    your_result = Account.includes(:apartment, :apartment => :house, :apartment => {:house => :street}).where(:apartment => {:number => ...}).where(:house => {:number => ...}).where(:street => {:name => ...})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多