Search code examples
javaspring-bootelasticsearchspring-data-elasticsearch

How to return distance and all fields using elasticsearch and spring-boot (springframework.data.elasticsearch)


I found a way to get my data using elasticsearch query. But my current problem is to translate it in spring boot query.

My query is the following:

{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "should": [
        {
          "constant_score": {
            "filter": {
              "term": {
                "my_field": "my_value"
              }
            },
            "boost": 10
          }
        },
        {
          "constant_score": {
            "filter": {
              "term": {
                "my_field": "my_value"
              }
            },
            "boost": 8
          }
        }
      ],
      "filter": [
        {
          "terms": {
            "my_array_field": [
              "first_value",
              "second_value"
            ]
          }
        },
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 40,
              "lon": 2
            }
          }
        }
      ]
    }
  },
  "script_fields": {
    "distance": {
      "script": "doc['location'].arcDistance(40, 2) / 1000"
    }
  },
  "_source": true,
  "sort": [
    {
      "_score": "desc"
    }
  ]
}

All documents stored in the index have a fields location, with a type defined as a geo_point

My question is:

How to translate the script_fields, which is returning me the distance, using spring-boot.

My current code is:

BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(PageRequest.of(page, size))
                .build();

elasticsearchOperations.search(nativeSearchQuery, MyIndexedDocument.class);

I tried to use ScriptField from here and saw an example here but didn't find any solution for now.

  1. How should I use it?
  2. If think, after finding how to return distance, I will have to precise to my query that I want all the _source field in return. Is it possible to precise it using NativeSearchQuery ?

Solution

  • Answer as a workaround

    I let the question without any validated answer in case of somebody has a better answer.

    In case it's a question which is relevant for somebody, I finally choose to deal the distance return by using geo distance sort.

    The query is something like this:

    {
      "from": 0,
      "size": 10,
      "query": {
        "bool": {
          "should": [
            {
              "constant_score": {
                "filter": {
                  "term": {
                    "my_field": "my_value"
                  }
                },
                "boost": 10
              }
            },
            {
              "constant_score": {
                "filter": {
                  "term": {
                    "my_field": "my_value"
                  }
                },
                "boost": 8
              }
            }
          ],
          "filter": [
            {
              "terms": {
                "my_array_field": [
                  "first_value",
                  "second_value"
                ]
              }
            },
            {
              "geo_distance": {
                "distance": "10km",
                "location": {
                  "lat": 40,
                  "lon": 2
                }
              }
            }
          ]
        }
      },
        "sort" : [
            { "_score": "desc"},{
          "_geo_distance": {
            "location": {
                          "lat": 40,
                          "lon": 2
            },
            "order": "asc",
            "unit": "km",
            "mode": "min",
            "distance_type": "arc",
            "ignore_unmapped": true
          }
        }
       ]
    }
    

    So I can get my distance in return, but not as a field of content, but as a value in sortvalues

    Using spring data elasticsearch:

    BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    ScoreSortBuilder scoreSortBuilder = new ScoreSortBuilder();
    GeoDistanceSortBuilder geoDistanceSortBuilder = new GeoDistanceSortBuilder("location", Double.parseDouble(location.getLatitude()), Double.parseDouble(location.getLongitude()));
    geoDistanceSortBuilder.unit(DistanceUnit.KILOMETERS);
    geoDistanceSortBuilder.ignoreUnmapped(true);
    geoDistanceSortBuilder.sortMode(SortMode.MIN);
    geoDistanceSortBuilder.order(SortOrder.ASC);
    
    NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                    .withQuery(boolQueryBuilder)
                    .withPageable(PageRequest.of(page, size))
                    .withSort(scoreSortBuilder)
                    .withSort(geoDistanceSortBuilder)
                    .build();
    
    elasticsearchOperations.search(nativeSearchQuery, MyIndexedDocument.class);