Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geo Search Option? #12

Closed
iolson opened this issue Aug 15, 2016 · 16 comments
Closed

Geo Search Option? #12

iolson opened this issue Aug 15, 2016 · 16 comments

Comments

@iolson
Copy link

iolson commented Aug 15, 2016

I was wondering if people would be interested in possibly a trait to say setup this entry to be able to be geo-searched on. As Algolia and Elasticsearch are separate in the way they do this, so it would require some setup in terms of how to get things setup for the array. If there is interest I can create a PR for this functionality.

@the907
Copy link

the907 commented Sep 6, 2016

Any movement on this?

I would be interested in helping!

@iolson
Copy link
Author

iolson commented Sep 6, 2016

I can start looking at getting things setup. Just got pulled away on a client project.

@brino
Copy link
Contributor

brino commented Sep 11, 2016

For Elasticsearch the best way to do this would be to index a geo field and then add a function_score query to the should "clause" of a bool query. This increases the score based on distance from indexed doc's field val to the user's given origin.

To set up the query you need at minimum:

  • origin location lat/lon pair of the searcher
  • scale (radius distance from origin point)

Could also allow more options for:

  • offset (makes the search area more of a doughnut shape, excluding a smaller circle in the center)
  • decay_function (exp, linear, or gauss) uses different maths to calculate, may need to change for performance issues
  • decay (how quickly the score boosting effect tapers off)

This would also mean that a special "location" field be indexed in advance for the query to run against.

That all being said, whats the general idea here? How would this geo search mechanism work in practice?

@sandervanhooft
Copy link

This would be great!

@EdwardNelson
Copy link

EdwardNelson commented Sep 22, 2016

I had an attempt with #77. Going with what Taylor said what does everyone believe would be an elegant way to include additional functionality from Algolia and Elasticsearch and what are they key features that should be included?

I believe the following are important:

  • Geosearch

Maybe something like this:

Model::search('querystring')->withinLocation($lat, $lng, $radius)->get();

See #78

@sandervanhooft
Copy link

Before querying, the field mapping should be prepared to handle geopoints. This can only be done with a new/empty index as I understand it.

Is this possible using Scout, or do we need an external workaround for this?

I'll try to map geopoints directly using ES, before indexing documents with Scout, hopefully next week...

@EdwardNelson
Copy link

@sandervanhooft From this article it seems that sticking to convention means that a mapping does not need to be made. I believe that means it is then up to the developer to correctly set up their toSearchableArray() method on their model. However, I am not too familiar with ES. Let me know if my understanding is wrong

@sandervanhooft
Copy link

@EdwardNelson Thanks for the article. It unfortunately mentions that since the update you do need to provide a mapping.

@EdwardNelson
Copy link

@sandervanhooft my fault for skimming the article and hoping for the best! You're completely right. Having to set the mappings on creation of the index and with updating the mappings once the index has been created having the potential to cause problems means that geosearch probably shouldn't be supported in scout? As not everyone will include lat/long from the outset. What's your opinion

@sandervanhooft
Copy link

@EdwardNelson It depends on whether Scout breaks the geofield mapping after
having set it manually. I plan to try that next week. Feel free to beat me
to it :).

If that works than geosearch can IMHO be supported from Scout (and should
be), with a sidenote on the mapping process.

For me personally, Scout is potentially incredible valuable for getting
data easily into ElasticSearch. In my current setup I poll
ElasticSearch through a isolated frontend, so the value of retrieval
through Laravel Scout is not that high for me. This may change when more
complex queries are supported. But because of the "abstraction layer"
nature of Scout, I suspect it will never support all current ElasticSearch
features.

Nevertheless, geospatial search is such a basic requirement I hope to see
it fulfilled for and by the Laravel community. I don't feel fluent enough
in Laravel to assist in this implementation, but am happy to help in any
way I can.
On Sat, 24 Sep 2016 at 11:51, EdwardNelson [email protected] wrote:

@sandervanhooft https://github.com/sandervanhooft my fault for skimming
the article and hoping for the best! You're completely right. Having to set
the mappings on creation of the index and with updating the mappings once
the index has been created having the potential to cause problems means
that geosearch probably shouldn't be supported in scout? As not everyone
will include lat/long from the outset. What's your opinion


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#12 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AG7dp7KlSEbHaaJmaAinxrwaPt5C2oosks5qtPKXgaJpZM4JkHTT
.

@sandervanhooft
Copy link

sandervanhooft commented Sep 26, 2016

@EdwardNelson I am happy to report that manually mapping works! :)

It takes 2 steps to get the geopoints into ElasticSearch:

  1. Manually prepare the elasticsearch type mapping for storing a geopoint field
  2. Prepare your Laravel model

1. Manually prepare the elasticsearch type mapping for storing a geopoint field
Set up an explicit location type mapping in ElasticSearch prior to loading any data into it. You will not be able to change the mapping once there's data stored in the index (Or in ElasticSearch jargon: do this before documents are indexed for this type.) See example code below.

You only need to provide mapping for fields that are not automatically interpreted correctly by ElasticSearch. So in my case I only provided the location mapping.

I think the nicest way to do this manual mapping is actually to use a Laravel migration and the elasticsearch/elasticsearch package and the connection config used for Scout to set this up.

Anyone up for writing an example for this?

2. Prepare your Laravel model
ElasticSearch accepts a location in these forms:

  • Geo-point expressed as an object, with lat and lon keys.
  • Geo-point expressed as a string with the format: "lat,lon".
  • Geo-point expressed as a geohash.
  • Geo-point expressed as an array with the format: [ lon, lat] (mind that lon comes before lat!)

The Laravel Scout searchable trait is very easy to use if you have stored the location in a single table field, so it matches the Geo-point lat,lon string format or the geohash format . This way you don't need to do any customization and can stick to the formal Laravel Scout docs. If you have used two fields for lon and lat in your table than you'll need to provide a customized Model->toSearchableArray method to provide ElasticSearch with the correct format.

After this you can use Laravel Scout as you would normally use it.

Example mapping (source):

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "location": {
          "type": "geo_point"
        }
      }
    }
  }
}

With cURL this would be:

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "location": {
          "type": "geo_point"
        }
      }
    }
  }
}

@EdwardNelson
Copy link

@sandervanhooft Probably getting a bit out of my depth in terms of Elasticsearch. It looks good from my amateur eyes! Probably one for the docs if it can be condensed down? Any chance you can take a look at #78 to see if we can get it merged.

@brino
Copy link
Contributor

brino commented Sep 27, 2016

From an elasticsearch point of view. Yes, I think this would do a fine job of filtering results outside of radius from origin!

@EdwardNelson
Copy link

Excellent, thanks!

@xcaptain
Copy link
Contributor

I wrote an example in ErickTamayo/laravel-scout-elastic#24

@driesvints
Copy link
Member

You can use the example from here in order to achieve this: ErickTamayo/laravel-scout-elastic#24 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants