RAUSHAN KUMAR RAUSHAN KUMAR - 4 months ago 17
PHP Question

elastic serach find documents based on location

I am using elastic search 1.4 with couchbase 3.2. I have to find all the documents based on the location. As for example i have to find the user latitude and longitude and display all the events nearby him for which his interests matched. I am storing event data on couchbase as.

{
"createdUnder": "11",
"createdby": "4",
"name": "Vcunnect April Event Testing",
"location": "Madurai, Tamil Nadu, India",
"address": {
"venuename": "MKU University",
"address1": "MKU University",
"address2": "MKU University",
"city": "Madurai",
"state": "Tamil Nadu",
"country": "India",
"zipcode": "875485"
},
"description": "Vcunnect testing Event\r\n",
"lat": "9.9252007",
"lng": "78.11977539999998",
"startdate": "08/10/2016",
"enddate": "08/10/2016",
"starttime": "5:20pm",
"endtime": "7:00pm",
"organisers": [
{
"organisername": "Raushan Kumar",
"organiseremail": "raushankumar@gmail.in",
"organiserdescription": "Event Organizer",
"status": "active"
}
],
"starttimestamp": 1470867600,
"endtimestamp": 1470873600
}


I have two fields as "lat" and "lng" in my document. using this and user location latitude and longitude i want to find the events nearby the user. I am using this query for getting the documents.

$searchParams['index'] = 'events';
$searchParams['type'] = 'couchbaseDocument';
$searchParams['from'] = 0;
$searchParams['size'] = 1000;
$searchParams['body']['query']['filtered']['filter']['bool']['must'][]['term']['displaystatus'] = 0;
$searchParams['body']['query']['filtered']['filter']['bool']['must'][]['term']['eventstatus'] = "active";
$searchParams['body']['query']['filtered']['filter']['bool']['must'][]['range']['starttimestamp']['from'] = $today;
$searchParams['body']['query']['filtered']['filter']['bool']['must'][]['term']['displayoutside'] = 1;
$searchParams['body']['query']['filtered']['filter']['bool']['must'][]['terms']['cat_id'] = $interestIdArray;
$result = $client->search($searchParams);


My mapping in the json file is as

{
"template" : "*",
"order" : 10,
"mappings" : {
"couchbaseCheckpoint" : {
"_source" : {
"includes" : ["doc.*"]
},
"dynamic_templates": [
{
"store_no_index": {
"match": "*",
"mapping": {
"store" : "no",
"index" : "no",
"include_in_all" : false
}
}
}
]
},
"_default_" : {
"_source" : {
"includes" : ["meta.*"]
},
"properties" : {
"meta" : {
"type" : "object",
"include_in_all" : false
}
}
}
}
}


I have five indices at my elasticsearch cluster named "events,groups,chatmessages,sponsors and userdata". From them i want to location based mapping for only events and groups indices. What i have to changed..?

Answer

Note: this answer is specific to ES 1.x, the syntax will be somewhat different in 2.x

If you want to store coordinates in a way that will be queryable in Elasticsearch, you have to do the following:

  1. Store the lat/lon in a format that ES will be able to map to a geo_point, which means either as sub-properties of an object { 'location': {'lat': 123, 'lon': 123}}, or as an array [<lon>, <lat>] (note the order here).
  2. Manually update the ES mapping to treat your location field as a geo_point type. Take a look here for an example: https://www.elastic.co/guide/en/elasticsearch/reference/1.4/mapping-geo-point-type.html
  3. Use one of the geo filters to query by distance/range/bounding shape, e.g. geo_distance filter: https://www.elastic.co/guide/en/elasticsearch/reference/1.4/query-dsl-geo-distance-filter.html

Example:

Document mapping fragment to index the location as a geo_point type:

{
    "data" : {
        "properties" : {
            "location" : {
                "type" : "geo_point"
            }
        }
    }
}

Document with a location:

{
    "data" : {
        "location" : {
            "lat" : 9.9252007,
            "lon" : 78.11977539999998
        }
    }
}

Query to find documents with a location within a 10km radius of some point (should return at least the preceeding example doc):

{
    "filtered" : {
        "query" : {
            "match_all" : {}
        },
        "filter" : {
            "geo_distance" : {
                "distance" : "10km",
                "data.location" : {
                    "lat" : 9.9,
                    "lon" : 78.12
                }
            }
        }
    }
}
Comments