brupm
brupm

Reputation: 1183

Solr (Sunspot) query time boost on non keyword searches

Given that I want to find 20 relevant results how would I go about boosting the first criteria inside any_of (with(:id).any_of(co_author_ids)) so that if there are 20 results which match said criteria it will return as opposed to trying to match based on the second criteria?

@solr_search = User.solr_search do
  paginate(:per_page => 20)
  with(:has_email, true)

  any_of do      
    with(:id).any_of(co_author_ids)        
    with(:hospitals_id).any_of(hopital_ids)
  end
end

Initially I didn't think boosting was necessary as I figured any_of would have a cascading effect but it does not appear to work like that. I know who to do query time boosting on keywords and fulltext searches but have been unable to get it working with with() methods.

Upvotes: 4

Views: 776

Answers (1)

Sahil Dhankhar
Sahil Dhankhar

Reputation: 3656

since co_author_ids is a multivalued key , i have enough reasons to believe that there is no way to achieve that. although with single value keys it is possible to achive this cascading effect by using solr sort using function query. http://wiki.apache.org/solr/FunctionQuery#Sort_By_Function aong with the adjust_solr-params http://sunspot.github.io/docs/Sunspot/DSL/Adjustable.html

Example: suppose you have query like this:

@solr_search = User.solr_search do
  paginate(:per_page => 20)
  with(:has_email, true)
  any_of do      
    with(:id,author_id) #assuming author id is a solr index        
    with(:hospitals_id).any_of(hopital_ids)
  end
end

and now in this case you want to have a cascading effect and want to give more preference to exact matches with author_id you can do this way

@solr_search = User.solr_search do
  paginate(:per_page => 20)
  with(:has_email, true)
  any_of do      
    with(:id,author_id) #assuming author id is a solr index        
    with(:hospitals_id).any_of(hopital_ids)
  end
  adjust_solr_params do |p|
    p["sort"] = "if(author_id_i = #{id},1,0) desc" #note author_id_i solr eq of author_id
  end  
end

so this will sort on the basis of the value of if(author_id_i = #{id},1,0) and in return will put all the records with auhtor_id as same of the user on top.

i somehow was getting problems using IF function so i instead used (practicaaly both of them are same):

@solr_search = User.solr_search do
  paginate(:per_page => 20)
  with(:has_email, true)
  any_of do      
    with(:id,author_id) #assuming author id is a solr index        
    with(:hospitals_id).any_of(hopital_ids)
  end
  adjust_solr_params do |p|
    p[:sort] = "min(abs(sub(author_id_i,#{id})),1) asc" 
  end  
end

i stumbled upon this also http://wiki.apache.org/solr/SpatialSearch while looking for a solution for this and if you want to sort by distance you can do something like:

@solr_search = User.solr_search do
  paginate(:per_page => 20)
  with(:has_email, true)
  any_of do      
    with(:id,author_id) #assuming author id is a solr index        
    with(:hospitals_id).any_of(hopital_ids)
  end
    adjust_solr_params do |p|
      p[:pt] = "#{latitude_of_your_interest},#{longitude_of_your_interest}"
      p[:sfield] = :author_location #your solr index which stores location of the author
      p[:sort] = "geodist() asc"
    end
end

overall i would say you can do a lot of cool things with p["sort"] but in this particular case it cant be done( imho) because it being a multivalued field ex: Using multivalued field in map function Solr function query that operates on count of multivalued field

I wish they could just provide a include function for multivalued field and we can just write p["sort"] ="if(include(co_authors_ids,#{id}), 1, 0) desc"

but as of now its not possible(again imho).

Upvotes: 5

Related Questions