feat(search): geo predicates in KQL (distance, bbox, polygon) - #3212
feat(search): geo predicates in KQL (distance, bbox, polygon)#3212dschmidt wants to merge 5 commits into
Conversation
Extends the KQL grammar with geo function values on any field, e.g. location:geo.distance(lat, lon, 5km). Parses into GeoDistance/GeoBoundingBox/ GeoPolygon AST nodes; radius units (km/m/mi) are normalised to meters.
Translates the geo AST nodes to bleve GeoDistance/GeoBoundingBox/ GeoBoundingPolygon queries over the indexed <field>_geopoint sibling.
Not up to standards ⛔🟢 Coverage
|
| Metric | Results |
|---|---|
| Coverage variation | ✅ +0.29% coverage variation (-1.00%) |
| Diff coverage | ✅ 73.45% diff coverage |
Coverage variation details
Coverable lines Covered lines Coverage Common ancestor commit (1b697e4) 82737 19353 23.39% Head commit (8149819) 83205 (+468) 19706 (+353) 23.68% (+0.29%) Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch:
<coverage of head commit> - <coverage of common ancestor commit>
Diff coverage details
Coverable lines Covered lines Diff coverage Pull request (#3212) 516 379 73.45% Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified:
<covered lines added or modified>/<coverable lines added or modified> * 100%
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Adds geo_distance/geo_bounding_box query builders plus a geo_shape polygon query (relation intersects, the modern replacement for the deprecated geo_polygon, still valid against geo_point). Wires the geo AST nodes through the KQL transpiler onto the <field>_geopoint sibling.
dd79aee to
dfb20f9
Compare
| // geoField maps a KQL geo key to its indexed geopoint sibling, e.g. | ||
| // "location" to "location_geopoint". | ||
| func geoField(key string) string { | ||
| return strings.ToLower(key) + mapping.GeopointSuffix |
There was a problem hiding this comment.
Uh, this is bad. Should do a proper lookup of the fieldname. This currently works, as we only have the location - but not in the generic case
…n-geo fields Replaces the ad-hoc key+"_geopoint" concatenation with a proper lookup (query.ResolveGeoField) derived from the TypeGeopoint field overrides, so it works for any geopoint field, not just location. Geo predicates on non-geopoint fields now error instead of querying a nonexistent field.
…haviour Sorts the two latitudes in the KQL layer so MinLat <= MaxLat. Only bleve strictly requires it (it errors on an inverted box; OpenSearch tolerates it), but doing it centrally keeps behaviour consistent across backends and the AST easy to reason about. Longitude order is preserved so an antimeridian-crossing box (minLon > maxLon) still works, which both backends handle identically.
This is a non standard extension to KQL. If you want an ADR first, let me know...
Adds geo predicates to KQL, usable on any geopoint field wherever KQL is accepted (graph search, webdav search REPORT, ...):
location:geo.distance(lat, lon, 5km)(radius units km/m/mi)location:geo.bbox(minLat, minLon, maxLat, maxLon)location:geo.polygon(lat lon, lat lon, ...)They compose in the boolean tree, e.g.
mediatype:image AND location:geo.distance(48.2, 16.3, 5km). No proto, graph-endpoint or mapping change: thelocation_geopointindex sibling already comes from #2659, and the filter rides in the query string.Stacked on #2659. Three commits: KQL grammar/AST/parse, bleve compiler, opensearch transpiler.
No sort-by-distance: KQL only filters, that would need a structured request param.