微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ruby-on-rails – Rails 3多模型查询

我有以下型号:

class Location < ActiveRecord::Base
    has_many :location_items
    has_many :items,:through=>:location_items
end

class Item < ActiveRecord::Base
    has_many :location_items
    has_many :locations,:through=>:location_items
end

class LocationItem < ActiveRecord::Base
    belongs_to :item
    belongs_to :location
end

此外,我可以为项目模型启用全文搜索(来自gem),我可以这样做
Item.search(‘keyword’) – ‘search’是gem提供的范围,用于获取所有名称或描述匹配关键字的项目,结果项目添加了’rank’属性以匹配相关性

我也可以为位置模型启用Geo搜索(来自gem),我可以这样做
Location.near(‘Toronto.ON’,100)—‘near’是宝石提供的范围,用于获取距离多伦多100公里范围内的所有位置,结果位置添加了距离给定距离的“距离”属性location – 这个例子中的多伦多

所以现在我要做的是获取一个location_item对象列表,这些对象的位置匹配某个给定的位置和项目匹配给定的关键字.
例如,搜索匹配“关键字”且位于多伦多100公里范围内的location_item对象.

如何通过一个查询实现此目的?并且还可以通过location_item对象内的关联项和位置访问距离和排名属性.

我似乎无法链接范围,因为他们只处理Item和Location,而不是LocationItem,

例如,下面的表达式将不起作用

LocationItem.joins(:items,locations).search(‘keyword’).near(‘Toronto,ON’,100)

希望我对我想要做的事情的描述是有道理的.你有什么主意吗?非常感谢你!

解决方法

基本上,您将无法在一个查询中执行您想要的所有操作并保留您正在查找的常规LocationItem#location和LocationItem#item接口.我将假设您正在使用Postgres的全文搜索,因为如果您使用Solr或Sphinx **,这个问题没有意义*.

如果你想要一个查询,但不介意放弃你返回的元素的belongs_to接口:ActiveRecord :: Base自动分配查询的SELECT部分​​提供的属性,如下所示:Location.select( ‘id 1 as more_id’).first.more_id#=> 2这样您就可以使用它,并创建具有位置和item以及item_rank和location_dist的相应部分的属性.

class LocationItem < ActiveRecord::Base

  #This presumes that your geo and search gems actually return scopes that 
  # properly respond to to_sql (which they should if you're using rails 3).
  def self.local_matching_items(text,dist=100)
    LocationItem
      .joins("INNER JOIN #{Item.search(text).to_sql} as matching_items 
                                          on matching_items.id 
                                          = location_items.item_id")
      .joins("INNER JOIN #{Location.near(dist).to_sql} as nearby_locations
                                            on nearby_locations.id 
                                            = location_items.location_id")
      .select("location_items.id,nearby_locations.distance,matching_items.rank,nearby_locations.other_field_you_might_want as
                location_other_field_you_might_want,matching_items.name as item_name,etc")
      #returns LocationItems with #id,#distance,#rank,# location_other_field_you_might_want,#item_name,etc
              #It might be most helpful to distinguish between these
              # and normal location_item's by storing them in variables with a 
              # different naming convention like nearby_item_matches.
  end
end

*因为那时你会做两个查询,一个用于通过搜索提供商匹配关键字,一个用于从数据库获取记录.

**如果您正在使用ThinkingSphinx,它已经支持searching by geographical distance,但您必须以不同方式定义索引并以不同方式调用LocationItem #search.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐