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

@ -64,6 +64,7 @@ type ScanWriterParams struct {
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,24 +324,12 @@ func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
defer sw.mu.Unlock()
}
keepGoing := true
if !sw.globEverything {
if sw.globSingle {
if sw.globPattern != opts.id {
if !opts.ignoreGlobMatch {
var match bool
match, keepGoing = sw.globMatch(opts.id, opts.o)
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)
if !ok {

View File

@ -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
@ -347,10 +348,11 @@ func (c *Controller) cmdNearby(msg *server.Message) (res resp.Value, err error)
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 {
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
})