1
votes

Background:

We have requirement for following:

  1. Data matching keyword should be returned.
  2. Data has longitude and latitude fields, result should be near specified lat long.
  3. Returned result should contain distance field, which specified distance between given lat long and lat long contained in data.
  4. Data should be sorted accouding to MultiMatch score.

Reading the tutorial in this link Spatial Search ElasticSearch tutorial I have constructed following query in C#.

 var res = await _elasticClient
            .SearchAsync<Results>(
                s =>
                    s.Type("Data")
                        .Skip(skip)
                        .Take(limit)
                      .SortGeoDistance(es => 
                            es.Ascending().OnField("Coordinates").Unit(GeoUnit.Kilometers).PinTo(lat,lng))
                      .Query(
                        q1 =>
                            q1.Filtered(
                                f1 =>
                                    f1.Query(q2 => q2.MultiMatch(mm => mm.OnFields(MultiMatchFieldsArray)
                                    .Query(keyword)
                                    .Type(TextQueryType.MostFields)))
                                    .Filter(f2 => f2.GeoDistance("Coordinates",gf => gf.Distance(10,GeoUnit.Kilometers)
                                    .Location(lat,lng))))));

According to tutorial I have to use SortGeoDistance method to get distance in result. Using SortGeoDistance will sort result according to distance, but in need result to be sorted according to MultiMatch score.

1

1 Answers

2
votes

Following Stackoverflow answer shows how to get distance without using sort.

Below is C# equivalent of the answer.

var esSearch = await _elasticClient
            .SearchAsync<Results>(
                s =>
                    s.Type("Data")
                      .Skip(skip)
                      .Take(limit)
                      .Fields("_source")
                      .ScriptFields(sf => sf.Add("Distance", des => des.Params(param => param.Add("lat", lat).Add("lon", lng)).Script("doc[\u0027Coordinates\u0027].arcDistanceWithDefault(lat,lon,-1)")))
                      .Query(
                        q1 =>
                            q1.Filtered(
                                f1 =>
                                    f1.Query(q2 => q2.MultiMatch(mm => mm.OnFields(MultiMatchFields)
                                    .Query(keyword)
                                    .Type(TextQueryType.MostFields)))
                                    .Filter(f2 => f2.GeoDistance("Coordinates",gf => gf.Distance(10,GeoUnit.Kilometers)
                                    .Location(lat,lng))))));