思维狮身人面像的复杂搜索

时间:2012-08-04 13:55:27

标签: ruby-on-rails-3 thinking-sphinx

我想用思考狮身人面像进行复杂的搜索:

搜索以下用户: - >住在城市(city_id属性) - >或者有能力搬到城市(mobile_cities association) - >或者距离纬度/经度点的最大距离,每个用户的最大距离不同,并在mobility_distance属性中设置。

现在我用3个不同的搜索做了,我volontary设置了一个很大的per_page数,然后我将3个结果合并到一个数组上,然后分页这个数组:

#users living in the @city
search_set_living = search_set.merge({:city_id => @city.id })
users_living =  User.search :with => search_set_living.dup,
                                :page => 1, :per_page => 1000

#users declaring hability to move to the @city
search_set_mobile = search_set.merge({:mobile_cities_ids => @city.id })
users_mobile =  User.search :with => search_set_mobile.dup, :page => 1, :per_page => 1000

#users living at a maximum distance from the origin point(custom distance for each user, max 30km)   
search_set_around = search_set.merge({"@geodist" => 0.0..30_000.0})
users_around =  User.search :geo => [@search_latitude * Math::PI / 180 , @search_longitude * Math::PI / 180],
                                  :with => search_set_around.dup,
                                  :page => 1, :per_page => 1000
users_around_filtered = users_around.dup.delete_if{|user| (user.mobility_distance * 1000 )< user.sphinx_attributes['@geodist'] }


#merge the 3 results in a array
all_users =  (users_mobile.flatten + users_around_filtered.flatten).uniq

#look for facets and paginate the array
@facets = User.facets :with => {:user_id => all_users.map(&:id)}
@users_to_display =  all_users.paginate(:page => params[:page], :per_page => 10)

这很好但我不满意: 性能不太好, - 我想要能够对这样的多个属性进行排序:order =&gt; “created_at DESC,@ relance DESC”

我希望在单个sphinx的搜索中进行完全相同的搜索。 我知道我应该使用"OR Logic with Attribute Filters" from the docs,但我不知道如何将它与geo_search调用混合... 我真的不知道该怎么做, 你能帮助我吗?

非常感谢,

2 个答案:

答案 0 :(得分:3)

正如您猜测的那样,:sphinx_select选项绝对是您的朋友。让我们一点一点地把它拼凑起来:

logic = [
  "city_id = #{@city.id}",
  "IN(mobile_cities_ids, #{@city.id}",
  "GEODIST(lat, lng, #{lat}, #{lng}) < (mobility_distance * 1000)"
]

User.search :sphinx_select => "*, #{logic.join(" OR ")}) AS valid",
  :with => {:valid => true}

根据需要添加分页,根据需要调整属性名称(也许你的lat / lng属性被命名为其他名称)。我不认为您需要围绕该自定义属性进行IF调用,就像在文档中一样,但如果事情不适用,可能会给它一个机会。在一个方面也应该很好。

答案 1 :(得分:-1)

太棒了!非常感谢。我只需要纠正一点你的语法(缺少一些括号),以使其工作。 我不得不添加per_page和页面参数,不知道为什么。

logic = ["city_id = #{@city.id}",
         "IN(mobile_cities_ids, #{@city.id})",
         "GEODIST(latitude, longitude, #{@search_latitude * Math::PI / 180}, #{@search_longitude * Math::PI / 180}) < (mobility_distance * 1000)"]

search_set_logic = search_set.merge({:valid => true})
@users_to_display = User.search :sphinx_select => "*, (#{logic.join(" OR ")}) AS valid",
                 :with => search_set_logic.dup,
                 :sort_mode => :extended,
                 :order => "visibility DESC, last_login_at DESC",
                 :page => params[:page], :per_page => 10