Retrieving only matching locations

Hi all,

I have an index that stores set of locations as geo_point

    {
      ......,
      "locations" : [
         {
            "lat" : ...
            "lon" : ...
         },
        .......
      ]
    }

and I use query which works fine

{
   "sort": [{
      "_geo_distance": {
         "locations": {
            "lat": 38.7762021,
            "lon": 26.954897
         },
         "order": "asc",
         "unit": "km"
      }
   }],
   "query": {
      "filtered": {
         "filter": {
            "geo_distance": {
               "distance": "30km",
               "locations": {
                  "lat": 38.7762021,
                  "lon": 26.954897
               }
            }
         }
      }
   }
}

I just wonder if I can retrieve subset of locations. Lets say I have 1000 geo point in an index and I would like to retrieve 5 closest matching point. I have tried to make this with inner_hits and nested_filter. Also, I tried to sort the geo points but I could not manage it. I am not sure that I am on right track.

Could you please advise me if it is possible and if so how can I solve the problem?

Thanks

Hey,

can you share a fully-fledged example using nested/inner_hits - this means, include your mapping, index creation, document indexing with geo points and your query - so others can follow your steps.

--Alex

Hi Alex,

Here is the steps to reproduce the case.

PUT localhost:9200/geo

PUT /geo/test/_mapping
{
   "properties": {
      "locations": {
         "type": "geo_point"
      }
   }
}

And sample data to work on

POST localhost:9200/geo/test/1
{
    "locations": [
      {
        "lon": 27.09519515440661,
        "lat": 38.478413567935185
      },
      {
        "lon": 34.80236053466797,
        "lat": 39.81952667236328
      },
      {
        "lon": 39.83582532931803,
        "lat": 40.96827796407719
      },
      {
        "lon": 36.333538930028226,
        "lat": 41.28705790254833
      },
      {
        "lon": 30.37797194349696,
        "lat": 40.77331286046352
      },
      {
        "lon": 28.254863739013672,
        "lat": 37.468238830566406
      },
      {
        "lon": 34.62808663310784,
        "lat": 36.80608547444202
      },
      {
        "lon": 27.417057,
        "lat": 38.61295
      },
      {
        "lon": 30.023533189852515,
        "lat": 39.39730937110715
      },
      {
        "lon": 32.5051864924701,
        "lat": 37.89531395220301
      },
      {
        "lon": 32.508596011506825,
        "lat": 37.8492941159215
      },
      {
        "lon": 32.488811510405185,
        "lat": 37.87698760572874
      }
    ]
}

POST  localhost:9200/geo/test/2
{
    "locations": [
      {
        "lon": 32.51198884183816,
        "lat": 37.90110180235243
      },
      {
        "lon": 32.03915426223398,
        "lat": 36.540804011837125
      },
      {
        "lon": 30.750701764736277,
        "lat": 36.890245468561396
      },
      {
        "lon": 30.595000683221542,
        "lat": 36.84250172907872
      },
      {
        "lon": 29.130974405626603,
        "lat": 36.67013612740797
      },
      {
        "lon": 28.442826999999966,
        "lat": 37.021167
      },
      {
        "lon": 27.357373237609863,
        "lat": 37.056478551035404
      },
      {
        "lon": 29.059229208694887,
        "lat": 37.81761128155548
      },
      {
        "lon": 27.260725335147754,
        "lat": 37.843887300205395
      },
      {
        "lon": 27.138333320617676,
        "lat": 38.3168448192717
      }
    ]
}

Query

POST  localhost:9200/geo/test/_search
{
   "query": {
      "bool": {
         "must": [
            {
               "geo_distance": {
                  "distance": "100km",
                  "locations": {
                     "lon": 28.442826999999966,
                     "lat": 37.121167
                  }
               }
            }
         ]
      }
   },
   "inner_hits": {
      "matches": {
         "type": {
            "test": {   
               
            }
         }
      }
   },
   "sort": {
      "_geo_distance": {
         "locations": {
            "lon": 28.442826999999966,
            "lat": 37.121167
         },
         "order": "asc",
         "unit": "km"
      }
   }
}

I have tried almost every variation possible with inner_hits yet I didn't manage to get what I want. I am also not sure inner_hits is possible with geo points and it is the right way to solve the case.

"inner_hits": {
      "matchedpoints": {
         "type": {
            "test": {   
               "query": {
                  "geo_distance": {
                     "distance": "100km",
                     "locations": {
                        "lon": 28.442826999999966,
                        "lat": 37.121167
                     }
                  }
               }
            }
         }
      }
   }

what I want is to get/identify geo points that matches with given point and with from and size options of inner_hits to limit locations such as closest 3 lat/lon.

Thanks.

Hey,

inner_hitsonly work, when nested or parent child is used, which is not configured in your mapping.

--Alex

Hi,

Right, sorry I misread the documentation of inner_hits. I thought it was the way to get geo points in order. I was not sure about it. In fact, I did what I need with custom groovy script that calculates each location and sorts in order that might be expensive since I had to iterate and calculate the distances again. I didn't test implications fully yet. However, I believe It could be extracted through _geo_distance sorting. so It could be nice to have like

"sort": {
      "_geo_distance": {
         "locations": {
            "lon": 28.442826999999966,
            "lat": 37.101167
         },
         "order": "asc",
         "unit": "km",
         "extra" : {
               "name" : "closest_points",
               "limit" : 3
          }  
      }
   }

So it might be included _source if it is possible. It might be useful such use cases.

If there is better inbuilt way to handle this issue instead of custom script, please let us know.

Thanks.