1

I'm afraid I don't know the terminology to succinctly describe what I'm trying to do, but I will explain what I'm currently doing and what I'd like to do. I'm trying to converge two search queries into a single query, taking geo point data from one index to use a search parameter for searching in a second index/doctype.

My current ES set up:

Indices and DocTypes:

|- 1) locations
|---- 1a) UK_postcode

|- 2) accounts
|---- 2a) client

Each of the Doctypes has a field names 'location' which is mapped to a GeoPoint type.

My Current Process:

1) Users search for clients based on keywords and distance from location (a UK postcode).

2) System takes the postcode and searches for the matching results to get the geo_point latitude and longitude data from the locations.UK_postcode.

3) System uses the provided keywords and latitude and longitude to search on the accounts.client index/doctype.

4) System returns nice looking results to the user, based on ES search results.

My Question:

Can steps 2 and 3 be rolled into a single search query? If yes how do I do this? I want to pass a postcode to the search query and for ES to find the geo_point data for fulfilling the requirements of a geo distance query on the client doctype.

9
  • Is the distance always the same? i.e. when looking around a postcode are you always looking at (e.g.) 5km of the postcode location? (since we're talking geo_distance) Commented May 27, 2016 at 11:49
  • No the distance is a user supplied variable of the search. Commented May 27, 2016 at 12:34
  • So they formulate queries like "get me all the clients whose name starts with 'Comp' and located 11.5km around postcode ABC123"? Commented May 27, 2016 at 12:38
  • How does the user select the distance? Is there a pick list with predefined distances? Commented May 27, 2016 at 13:50
  • They enter a floating point number representing number of miles. Commented May 27, 2016 at 13:55

1 Answer 1

1

Using pre-indexed shapes, you can definitely eliminate step 2. Note that this solution only works with pre-defined distances.

The main idea would be:

  1. to store in your locations index a geo_shape of type circle for each postcode and each pre-defined distances.
  2. to store in your accounts index a geo_shape of type Point for your client location
  3. create a geo_shape query of type circle which would leverage the pre-indexed postcode shapes.

So as a quick example, you'd have this:

A. Create the postcode locations index:

PUT /locations
{
    "mappings": {
        "UK_postcode": {
            "properties": {
                "location": { "type" : "geo_shape" }
            }
        }
    }
}

B. Create client locations index

PUT /accounts
{
    "mappings": {
        "client": {
            "properties": {
                "name": { "type": "string" }
                "location": { "type" : "geo_shape" }
            }
        }
    }
}

C. Create sample postcode circle of 1, 2, 3 mile radius for "M32 0JG"

PUT /locations/UK_postcode/M320JG-1
{
    "location": {
        "type" : "circle",
        "coordinates" : [-2.30283674284007, 53.4556572899372],
        "radius": "1mi"
    }
}

PUT /locations/UK_postcode/M320JG-2
{
    "location": {
        "type" : "circle",
        "coordinates" : [-2.30283674284007, 53.4556572899372],
        "radius": "2mi"
    }
}

# ... repeat until radius = 10

D. Create sample client very close to "M32 0JG"

PUT /accounts/client/1234
{
    "name": "Big Corp"
    "location": {
        "type" : "point",
        "coordinates" : [-2.30293674284007, 53.4557572899372]
    }
}

E. Query all clients whose name matches "big" and who are in a 2-mile radius of the postcode "M32 0JG"

POST /accounts/client/_search
{
  "bool": {
    "must": [
      {
        "match": {
          "name": "big"               <--- free text name match
        }
      }
    ],
    "filter": {
      "geo_shape": {
        "location": {
          "indexed_shape": {
            "id": "M320JG-2",         <--- located within two miles of M32 0JG
            "type": "UK_postcode",
            "index": "locations",
            "path": "location"
          }
        }
      }
    }
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I see your line of thought, I wonder if I set each postcode's id to the actual postcode instead of the default. Then filter the client distance based on the location of the locations.UK_postcode.location value of the document with the matching ID (or postcode).
If you index your postcode documents with a universal ID (such as the postcode itself), it's certainly easier to get the location, i.e. you don't have to search for it, just GET it. It's still two operations, though.
Hmm, thank you for your help, you definitely pointed me in the correct direction. This, I think, will be the solution to the problem, I need to GET the postcode and then use its location values as a search variable for 'distance from' client location. I was too fixated on searching for the postcode data, when it was a matter of getting the postcode data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.