Sphinx - Add weight for geodistance - geolocation

I use Sphinx for searching, with the php api and I want to attribute weight for geodistance.
For example :
0 to 5 miles => +100
6 to 20 miles => +50
etc
Do you know how can I do that ?
Thanks.

Basic plan:
$->setSelect("*, IF(#grodist<20000,50,0)+IF(#grodist<5000,50,0)+#weight AS myweight");
$->setSortMod(SPH_SORT_EXTENDED,'myweight DESC');
(the exact syntax will depend on exactly how you using sphinx)
... also look at the INTERVAL() function - useful if have lots of intervals...

Related

Ruby on Rails, sum of an attribute of an attribute

I'm having some problems with my Ruby on Rails website. Let me explain.
I have a user model, it has many credits
In order to count, the credits for a user I do:
#user.credits.sum(:score)
This works fine.
Now have a model team, that has many users, and I want to find out the total number of credits, I found on another StackOverflow post this:
array.inject{|sum,x| sum + x }
So I thought for me it should look like that:
#team.users.inject{|sum,x| sum + x.credits.sum(:score)}
But this returns
#<User:0x00000101a7c180>
instead of the sum. Guess I'm doing something wrong. Don't hesitate if you have an idea.
Thanks
You have to set the initial value:
#team.users.inject(0){ |sum,x| sum + x.credits.sum(:score) }
You could also do:
#team.users.sum{ |x| x.credits.sum(:score) }

Grouped facets with elasticsearch

I'm looking for a way to display my facets in a grouped list. For example i have some users and a facet to filter by country, this gives me:
Country
Holland (5)
England (2)
Egypt (5)
Rwanda (2)
And what i would like to have is:
Europe
Holland (5)
England (2)
Africa
Egypt (5)
Rwanda (2)
I'm using the Tire gem in a Rails application, my models and relations are like this: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-option_groups_from_collection_for_select
I've googled for an example on this for hours, just can't find anything for nested /grouped facets what makes sense to me in Elasticsearch. Hope someone can help me in the right direction! Many thanks in advance!
Daniel
You can probably handle this by indexing the data in two ways and then just parse the outout. Use the "object" version to apply filters, and get your parsing version as a facet to display filters.
For example:
"mydocument":{
"attributes":[
"location":{
{"continent":"europe",
"country":"england"
},
"fur_style":"long"
],
"facets":[
{"location":"Europe##england"},
{"fur_style":"long"
]
}
when you get your data back, you'll have:
"facets":[
{"location":"Europe##england",
"total":5},
{"location":"africa##egypt",
"total":7}
{"fur_style":"long",
"total":3}
etc etc
]
In your application, you just have to loop through and break apart the terms using the ## delimiter (or whatever you want it to be).

Ruby On Rails - Geocoder - Near with condition

I'm using GeoCoder in my application. Now I need to search for objects in my database which are close to a position OR have specific attribute set. I would like to perform this action in one database query, because the database is realy huge.
I would like to have something like
Spot.near([lat,long],distance).where("visited = ?",true).
The distance and the visited attribute should be combined with an OR, not with an AND.
Does anyone have an idea how to do this?
Thank you!
Based off of this answer, you should be able to do something like:
near = Spot.near([lat, long], distance)
visited = Spot.where(visited: true)
near = near.where_values.reduce(:and)
visited = visited.where_values.reduce(:and)
Spot.where(near.or(visited))
I'm in the process of upgrading a Rails application from Rails 4 to Rails 7 and ran into this problem. While I have no doubt Luke's suggestion worked in earlier versions, it doesn't work in Rails 7 (I'm currently running activerecord-7.0.3.1.
In my particular case, I am using the geocoder near() method to return results that are within a 20 mile radius of the query, but I also wanted to use OR conditions to return results where the query was similar to the text values in either the name or location columns from the items table in an attempt to return relevant items that haven't been assigned latitude and longitude values.
In Rails 4, my solution was:
select("items.*").near(q, 20, select: :geo_only).tap do |near_query|
near_query.where_values.last << sanitize_sql([" OR items.location LIKE ? OR items.name LIKE ?", "%#{q}%", "%#{q}%"])
end
In Rails/ActiveRecord 7, the where_values() method no longer exists. Searching for an alternate solution led me to this post. I wound up spending a fair amount of time perusing the latest ActiveRecord and Arel code for a solution. Here's what I came up with,
Rails 7 solution:
t = Item.arel_table
arel_geo_conditions = Item.near(q, 20).where_clause.ast # ast: Abstract Syntax Tree
Item.where(arel_geo_conditions.or(t[:location].matches("%#{q}%").or(t[:name].matches("%#{q}%"))))

How to boost score of Solr search results based on criteria?

Background:
1 - I'm using WebSolr for this search.
2 - I have two fields stored in websolr - name and id.
I want to search for these entries based on name AND boost the search score based on this criteria:
if id in [x1,x2..xN] then +2
if id in [y1,y2..yN] then +1
else +0
From my research, the answer lies in the following
- Function query, or
- DisMaxQParser
I have looked at the documentation but IMO its not very comprehensive.
Any help is appreciated.
You can use boosts. Try a query like
name:searchString AND ( id:[x1 TO xN] ^2 OR id:[y1 TO yN]^1)
In addition to hkn's approach, you could also use DisMax query parser boost queries:
q=queryString
&defType=dismax
&qf=…
&bq=id:[x1+TO+xN]^3
&bq=id:[y1+TO+yN]^2
(Untested, but should convey the idea.)

Order by nearest - PostGIS, GeoRuby, spatial_adapter

I'm trying to do an order query that finds records nearest to the current_user.
I know the distance between the two points is: current_location.euclidean_distance(#record.position)
How can I work this into a PostGIS (or active_record/spatial_adapter) query?
To get the 5 closest:
SELECT * FROM your_table
ORDER BY ST_Distance(your_table.geom, ST_Geomfromtext(your point as wkt))
limit 5;
If you have a big dataset and know that you don't want to search further than , say 1 km, the query will be more efficient if you do:
SELECT * FROM your_table
WHERE ST_DWithin(your_table.geom, ST_Geomfromtext(your point as wkt, 1000)
ORDER BY ST_Distance(your_table.geom, ST_Geomfromtext(your point as wkt))
limit 5;
/Nicklas
Just in case somebody stumbles upon this issue in rails 4.
I am using rgeo gem and this works for me
scope :closest, ->(point) { order("ST_Distance(lonlat, ST_GeomFromText('# {point.as_text}', #{SRID}))").limit(5) }
To wrap this up, with everyone's help I've got it working how I wanted:
order("ST_Distance(items.position, ST_GeomFromText('POINT (#{current_location.y} #{current_location.x})', #{SRID}))")
If you really want to find literally the 5 records nearest to the current_user, consider neighborhood search, which is supported by KNN index in PostGIS 2.0 (see '<->' operator):
SELECT * FROM your_table ORDER BY your_table.geom <-> ST_Geomfromtext(your point as wkt, 1000) LIMIT 5
Look at the ST_Distance documentation in PostGIS.
If you dont NEED to use PostGIS, geo-kit does this perfectly using google or yahoo (I've only used Google) and in your queries you can sort by distance, its awesome..

Resources