ElasticSearch - Geo Spatial search on location array


(Athir) #1

Dear All, I am creating an index with two types Restaurant and Branch with Spring Data. Restaurant has many branches as nested type. When I create this mapping, Spring Data / ElasticSearch automatically converts the location field inside the Branch type as latitude , longitude array, hence geo spatial query is not possible. Here it is:

I want to perform a search on branch.location for geo spatial search, but elastic search is not treating location as geopoint, rather a string array, hence it is not possible, please suggest what I need to do or where I am getting wrong.

class Restaurant {
    @Field( type = FieldType.Nested)
    private List<Branch> branches = new ArrayList<Branch>();
}

class Branch {
   private GeoPoint location;
}

(David Pilato) #2

Please format your code using </> icon as explained in this guide. It will make your post more readable.

Or use markdown style like:

```
CODE
```

What does the mapping look like?
What does a typical Json document look like?


(Athir) #3

Thanks for your response David, I have formated the code. I am attaching the full class of Spring Data Mapping classes:

@Document(indexName = "index", type = "restaurant")
public class Restaurant {

	@Id
	private String id;
	private String name;
	private String name_ar;
	private String description;
	private String description_ar;
	
//	private GeoPoint location;
	
	@Field( type = FieldType.Nested)
	private List<BranchLocation> locations = new ArrayList<BranchLocation>();
//	private Map<Integer, GeoPoint> locations = new HashMap<Integer, GeoPoint>();
	
//	@Field( type = FieldType.Nested)
//	private List<Product> products = new ArrayList<Product>();
	
}

Branches class/mapping in Spring Data:

@Document(indexName = "index", type = "branch")
public class BranchLocation {
	@Id
	private String id;
	private String name;	
	private GeoPoint location	
//	@Field(type = FieldType.Nested, ignoreFields = {"restaurant"})
	private Restaurant restaurant;
}

This correctly creates the mapping as below:

{"index4":{"aliases":{},"mappings":{"branch":{"properties":{"location":{"type":"geo_point"}}},"restaurant":{"properties":{"locations":{"type":"nested","properties":{"location":{"type":"geo_point"}}}}}},"settings":{"index":{"refresh_interval":"1s","number_of_shards":"5","creation_date":"1511004142432","store":{"type":"fs"},"number_of_replicas":"1","uuid":"s8Pa8Ok2Tc2SNUJK-jEC1w","version":{"created":"2040099"}}},"warmers":{}}}

But then I use following code to insert values:

BranchLocation location = new BranchLocation("1001", "", 24.7007637D, 46.6463977D, null);
	locationRepository.save(location);
	BranchLocation location2 = new BranchLocation("1002", "", 24.7034429D,46.6801231D, null);
	locationRepository.save(location2);
	BranchLocation location3 = new BranchLocation("1003", "", 24.7035265D,46.6494806D, null);
	locationRepository.save(location3);
	BranchLocation location4 = new BranchLocation("1004", "", 24.7044622D,46.6869027D, null);
	locationRepository.save(location4);
	
	Restaurant rest = new Restaurant("001", "Bangkok Thai Restaurant", "مطعم بانكوك التايلاندي", "Bangkok Thai Restaurant Description", "مطعم بانكوك التايلاندي");
	rest.getLocations().add(location);
	rest.getLocations().add(location2);
	rest.getLocations().add(location3);
	rest.getLocations().add(location4);
	restaurantService.save(rest);

It changes the mapping to following, when I add data, which is correct now, but I am not able to execute the following query, my index contain 1 restaurant and 4 branches which has geo locations inside it, I want to search a restaurant based on the branch location with the following query, please tell me what I have done wrong here:

Geo Spatial Query:

{
  "from" : 0,
  "size" : 20,
  "query" : {
    "match_all" : { }
  },
  "post_filter" : {
    "geo_distance" : {
      "distance" : "25km",
      "locations.location" : { 
        "lat" : 24.7007637, 
        "lon" : 46.6463977 
      }      
    }
  }
}

After adding data in the index (restaurant and braches):
{"index5":{"aliases":{},"mappings":{"branch":{"properties":{"id":{"type":"string"},"location":{"properties":{"lat":{"type":"double"},"lon":{"type":"double"}}},"name":{"type":"string"}}},"restaurant":{"properties":{"description":{"type":"string"},"description_ar":{"type":"string"},"id":{"type":"string"},"locations":{"type":"nested","properties":{"id":{"type":"string"},"location":{"type":"geo_point"},"name":{"type":"string"}}},"name":{"type":"string"},"name_ar":{"type":"string"}}}},"settings":{"index":{"refresh_interval":"1s","number_of_shards":"5","creation_date":"1511005201064","store":{"type":"fs"},"number_of_replicas":"1","uuid":"5x9T44cKT8uJylT9HDZY_A","version":{"created":"2040099"}}},"warmers":{}}}

Please tell me where I am wrong, why the query is returning empty.


(David Pilato) #4

I can see this in your mapping.

"type":"nested"

Which means that when you query you need to use nested queries as well as internally nested documents are specific Lucene documents.


(Athir) #5

can you please transform the following query to suit my case, looking forward to your support.

{
  "from" : 0,
  "size" : 20,
  "query" : {
    "match_all" : { }
  },
  "post_filter" : {
    "geo_distance" : {
      "distance" : "25km",
      "locations.location" : { 
        "lat" : 24.7007637, 
        "lon" : 46.6463977 
      }
    }
  }
}

(David Pilato) #6

Have a look at https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html


(system) closed #7

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.