Filter id match before kNN results

fixes #280
This commit is contained in:
Josh Baker 2018-03-09 19:50:34 -07:00
parent 0ce2dab945
commit 248ccfbe8a
2 changed files with 54 additions and 32 deletions

View File

@ -59,11 +59,12 @@ type scanWriter struct {
} }
type ScanWriterParams struct { type ScanWriterParams struct {
id string id string
o geojson.Object o geojson.Object
fields []float64 fields []float64
distance float64 distance float64
noLock bool noLock bool
ignoreGlobMatch bool
} }
func (c *Controller) newScanWriter( func (c *Controller) newScanWriter(
@ -294,6 +295,28 @@ func (sw *scanWriter) fieldMatch(fields []float64, o geojson.Object) (fvals []fl
return 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 //id string, o geojson.Object, fields []float64, noLock bool
func (sw *scanWriter) writeObject(opts ScanWriterParams) bool { func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
if !opts.noLock { if !opts.noLock {
@ -301,23 +324,11 @@ func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
defer sw.mu.Unlock() defer sw.mu.Unlock()
} }
keepGoing := true keepGoing := true
if !sw.globEverything { if !opts.ignoreGlobMatch {
if sw.globSingle { var match bool
if sw.globPattern != opts.id { match, keepGoing = sw.globMatch(opts.id, opts.o)
return true if !match {
} 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
}
} }
} }
nfields, ok := sw.fieldMatch(opts.fields, opts.o) nfields, ok := sw.fieldMatch(opts.fields, opts.o)

View File

@ -328,6 +328,7 @@ func (c *Controller) cmdNearby(msg *server.Message) (res resp.Value, err error)
} }
sw.writeHead() sw.writeHead()
if sw.col != nil { if sw.col != nil {
var matched uint32
iter := func(id string, o geojson.Object, fields []float64, dist *float64) bool { iter := func(id string, o geojson.Object, fields []float64, dist *float64) bool {
if c.hasExpired(s.key, id) { if c.hasExpired(s.key, id) {
return true return true
@ -342,15 +343,16 @@ func (c *Controller) cmdNearby(msg *server.Message) (res resp.Value, err error)
} }
} }
return sw.writeObject(ScanWriterParams{ return sw.writeObject(ScanWriterParams{
id: id, id: id,
o: o, o: o,
fields: fields, fields: fields,
distance: distance, distance: distance,
noLock: true, noLock: true,
ignoreGlobMatch: s.knn,
}) })
} }
if s.knn { if s.knn {
nearestNeighbors(sw, s.lat, s.lon, iter) nearestNeighbors(sw, s.lat, s.lon, &matched, iter)
} else { } else {
sw.col.Nearby(s.sparse, s.lat, s.lon, s.meters, minZ, maxZ, sw.col.Nearby(s.sparse, s.lat, s.lon, s.meters, minZ, maxZ,
func(id string, o geojson.Object, fields []float64) bool { func(id string, o geojson.Object, fields []float64) bool {
@ -374,13 +376,22 @@ type iterItem struct {
dist float64 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) limit := int(sw.cursor + sw.limit)
var items []iterItem var items []iterItem
sw.col.NearestNeighbors(lat, lon, func(id string, o geojson.Object, fields []float64) bool { sw.col.NearestNeighbors(lat, lon, func(id string, o geojson.Object, fields []float64) bool {
if _, ok := sw.fieldMatch(fields, o); ok { if _, ok := sw.fieldMatch(fields, o); !ok {
dist := o.CalculatedPoint().DistanceTo(geojson.Position{X: lon, Y: lat, Z: 0}) return true
items = append(items, iterItem{id: id, o: o, fields: fields, dist: dist}) }
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 return len(items) < limit
}) })