I'm quite new to elasticsearch and spring-data-elasticsearch and I have some problems querying for nested objects.
I use the ElasticSearch repository to save an nested model instance in elasticsearch. As a result there is only one entry in elasticsearch containing all data, as far I understood this means I have a nested document.
I need to implement a relatively complex query using Criteria to build up the query iteratively. When I try to access a nested property using the dot notation like
startPoint.providingTimeRange.startTime
I don't get any search results (but matching data is present in elasticsearch).
In Spring Data Elastic Search with Nested Fields and mapping I found the capability of spring-data-elasticsearch to query for nested objects using the nestedQuery.
Is there any way to combine the Criteria search with the nestedQuery?
Thank you in advance, Christoph
Update 1: To provide some example code I created a demo project which contains similar nested objects like in my real project: https://github.com/empulse-gmbh/elasticsearchtest
The example is about to find FoodTrucks which are in a certain place in a certain time.
In this example I used a Repository to persist my nested entities.
I used two (both not working) approaches to query for nested objects:
/*
* add search criteria by timerange. it is assumed in timerange from
* is always before to.
*/
TimeRange searchTimeRange = foodTruckSearch.getSearchTimeRange();
if (searchTimeRange != null) {
String startTimePath = "locationPoint.timeRange.from";
String endTimePath = "locationPoint.timeRange.to";
searchCriteria = searchCriteria.and(
new Criteria(startTimePath).between(searchTimeRange
.getFrom().getTime(), searchTimeRange.getTo()
.getTime())).or(
new Criteria(endTimePath).between(searchTimeRange
.getFrom().getTime(), searchTimeRange.getTo()
.getTime()));
}
and:
TimeRange searchTimeRange = foodTruckSearch.getSearchTimeRange();
if (searchTimeRange != null) {
String startTimePath = "locationPoint.timeRange.from";
String endTimePath = "locationPoint.timeRange.to";
searchQuery.must(nestedQuery(
"locationPoint",
boolQuery().should(
rangeQuery(startTimePath).from(
searchTimeRange.getFrom().getTime()).to(
searchTimeRange.getTo().getTime())).should(
rangeQuery(endTimePath).from(
searchTimeRange.getFrom()).to(
searchTimeRange.getTo()))));
}
Update2: Thanks to Mohsin Husen I was able to use the nested search. The search by timerange works now. Additionally to Mohsin's suggestions I had to change the way of creating and starting the local Elasticsearch instance:
elasticSearchNode = NodeBuilder.nodeBuilder().clusterName("foodtruck-test").local(true).build();
Without giving the clusterName nested documents are not created.
My next (hopefully last) problem is using the geo_distance search filter. If I got it right in Elasticsearch I use queries for fuzzy searches like 'like' or 'range' and filters for yes/no or distance filters.
So I tried to use QueryBuilder and FilterBuilder together with spring-data-elasticsearch and failed.
According to the examples in the documentation I refactored my models so the Location class uses the spring-data-elasticsearch object GeoPoint.
For searching I use this:
/*
* add search criteria for radius search
*/
FilterBuilder searchFilter = null;
if (foodTruckSearch.getLatitude() != null
&& foodTruckSearch.getLongitude() != null) {
if (foodTruckSearch.getSearchRadiusInKilometers() == null) {
foodTruckSearch.setSearchRadiusInKilometers(5);
}
searchFilter = geoDistanceFilter("location.point")
.distance(
foodTruckSearch.getSearchRadiusInKilometers()
+ "km").lat(foodTruckSearch.getLatitude())
.lon(foodTruckSearch.getLongitude());
}
if (searchFilter != null) {
NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(
searchQuery, searchFilter);
return IteratorUtils.toList(foodTruckRepository.search(
nativeSearchQuery).iterator());
} else {
return IteratorUtils.toList(foodTruckRepository.search(searchQuery)
.iterator());
}
The exception I get is:
org.elasticsearch.action.search.SearchPhaseExecutionException: Failedtoexecutephase[query_fetch],
allshardsfailed;shardFailures{
[1][searchexample][0]: SearchParseException[[searchexample][0]: query[MatchNoDocsQuery],
from[0],
size[10]: ParseFailure[Failedtoparsesource[{
"from": 0,
"size": 10,
"query": {
"bool": {
}
},
"post_filter": {
"geo_distance": {
"location.point": [6.9599115,
50.9406645],
"distance": "10km"
}
}
}]]];nested: QueryParsingException[[searchexample]failedtofindgeo_pointfield[location.point]] ;
}
Is there any example available how to use geo_distance (nested?) filters with spring-data-elasticsearch?