From 248ccfbe8a20483056f5c226940aa7bcdb04c57a Mon Sep 17 00:00:00 2001 From: Josh Baker Date: Fri, 9 Mar 2018 19:50:34 -0700 Subject: [PATCH] Filter id match before kNN results fixes #280 --- controller/scanner.go | 55 ++++++++++++++++++++++++++----------------- controller/search.go | 31 ++++++++++++++++-------- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/controller/scanner.go b/controller/scanner.go index dedf004b..d48c67c9 100644 --- a/controller/scanner.go +++ b/controller/scanner.go @@ -59,11 +59,12 @@ type scanWriter struct { } type ScanWriterParams struct { - id string - o geojson.Object - fields []float64 - distance float64 - noLock bool + id string + o geojson.Object + fields []float64 + distance float64 + noLock bool + ignoreGlobMatch bool } func (c *Controller) newScanWriter( @@ -294,6 +295,28 @@ func (sw *scanWriter) fieldMatch(fields []float64, o geojson.Object) (fvals []fl return } +func (sw *scanWriter) globMatch(id string, o geojson.Object) (ok, keepGoing bool) { + if !sw.globEverything { + if sw.globSingle { + if sw.globPattern != id { + return false, true + } + return true, false + } + var val string + if sw.matchValues { + val = o.String() + } else { + val = id + } + ok, _ := glob.Match(sw.globPattern, val) + if !ok { + return false, true + } + } + return true, true +} + //id string, o geojson.Object, fields []float64, noLock bool func (sw *scanWriter) writeObject(opts ScanWriterParams) bool { if !opts.noLock { @@ -301,23 +324,11 @@ func (sw *scanWriter) writeObject(opts ScanWriterParams) bool { defer sw.mu.Unlock() } keepGoing := true - if !sw.globEverything { - if sw.globSingle { - if sw.globPattern != opts.id { - return true - } - keepGoing = false // return current object and stop iterating - } else { - var val string - if sw.matchValues { - val = opts.o.String() - } else { - val = opts.id - } - ok, _ := glob.Match(sw.globPattern, val) - if !ok { - return true - } + if !opts.ignoreGlobMatch { + var match bool + match, keepGoing = sw.globMatch(opts.id, opts.o) + if !match { + return true } } nfields, ok := sw.fieldMatch(opts.fields, opts.o) diff --git a/controller/search.go b/controller/search.go index e5a8a991..7c7cfe3d 100644 --- a/controller/search.go +++ b/controller/search.go @@ -328,6 +328,7 @@ func (c *Controller) cmdNearby(msg *server.Message) (res resp.Value, err error) } sw.writeHead() if sw.col != nil { + var matched uint32 iter := func(id string, o geojson.Object, fields []float64, dist *float64) bool { if c.hasExpired(s.key, id) { return true @@ -342,15 +343,16 @@ func (c *Controller) cmdNearby(msg *server.Message) (res resp.Value, err error) } } return sw.writeObject(ScanWriterParams{ - id: id, - o: o, - fields: fields, - distance: distance, - noLock: true, + id: id, + o: o, + fields: fields, + distance: distance, + noLock: true, + ignoreGlobMatch: s.knn, }) } if s.knn { - nearestNeighbors(sw, s.lat, s.lon, iter) + nearestNeighbors(sw, s.lat, s.lon, &matched, iter) } else { sw.col.Nearby(s.sparse, s.lat, s.lon, s.meters, minZ, maxZ, func(id string, o geojson.Object, fields []float64) bool { @@ -374,13 +376,22 @@ type iterItem struct { dist float64 } -func nearestNeighbors(sw *scanWriter, lat, lon float64, iter func(id string, o geojson.Object, fields []float64, dist *float64) bool) { +func nearestNeighbors(sw *scanWriter, lat, lon float64, matched *uint32, + iter func(id string, o geojson.Object, fields []float64, dist *float64) bool) { limit := int(sw.cursor + sw.limit) var items []iterItem sw.col.NearestNeighbors(lat, lon, func(id string, o geojson.Object, fields []float64) bool { - if _, ok := sw.fieldMatch(fields, o); ok { - dist := o.CalculatedPoint().DistanceTo(geojson.Position{X: lon, Y: lat, Z: 0}) - items = append(items, iterItem{id: id, o: o, fields: fields, dist: dist}) + if _, ok := sw.fieldMatch(fields, o); !ok { + return true + } + match, keepGoing := sw.globMatch(id, o) + if !match { + return true + } + dist := o.CalculatedPoint().DistanceTo(geojson.Position{X: lon, Y: lat, Z: 0}) + items = append(items, iterItem{id: id, o: o, fields: fields, dist: dist}) + if !keepGoing { + return false } return len(items) < limit })