mirror of https://github.com/tidwall/tile38.git
Merge pull request #652 from tidwall/geofence-where
Allow WHERE for geofence detection
This commit is contained in:
commit
d2953307a0
|
@ -191,8 +191,10 @@ func (c *Collection) Set(
|
|||
oldFieldValues = c.fieldValues.get(oldItem.fieldValuesSlot)
|
||||
newFieldValues = oldFieldValues
|
||||
newItem.fieldValuesSlot = oldItem.fieldValuesSlot
|
||||
if len(oldFieldValues) > 0 {
|
||||
oldFieldValues = append([]float64{}, oldFieldValues...)
|
||||
}
|
||||
}
|
||||
|
||||
if fields == nil {
|
||||
if len(values) > 0 {
|
||||
newFieldValues = values
|
||||
|
|
|
@ -294,6 +294,7 @@ func (s *Server) queueHooks(d *commandDetails) error {
|
|||
for _, hook := range candidates {
|
||||
// Calculate all matching fence messages for all candidates and append
|
||||
// them to the appropriate message slice
|
||||
hook.ScanWriter.loadWheres()
|
||||
msgs := FenceMatch(hook.Name, hook.ScanWriter, hook.Fence, hook.Metas, d)
|
||||
if len(msgs) > 0 {
|
||||
if hook.channel {
|
||||
|
|
|
@ -105,9 +105,18 @@ func fenceMatch(
|
|||
}
|
||||
detect = "roam"
|
||||
} else {
|
||||
var nocross bool
|
||||
// not using roaming
|
||||
match1 := fenceMatchObject(fence, details.oldObj)
|
||||
if match1 {
|
||||
match1, _, _ = sw.testObject(details.id, details.oldObj, details.oldFields)
|
||||
nocross = !match1
|
||||
}
|
||||
match2 := fenceMatchObject(fence, details.obj)
|
||||
if match2 {
|
||||
match2, _, _ = sw.testObject(details.id, details.obj, details.fields)
|
||||
nocross = !match2
|
||||
}
|
||||
if match1 && match2 {
|
||||
detect = "inside"
|
||||
} else if match1 && !match2 {
|
||||
|
@ -121,7 +130,7 @@ func fenceMatch(
|
|||
if details.command != "fset" {
|
||||
// Maybe the old object and new object create a line that crosses the fence.
|
||||
// Must detect for that possibility.
|
||||
if details.oldObj != nil {
|
||||
if !nocross && details.oldObj != nil {
|
||||
ls := geojson.NewLineString(geometry.NewLine(
|
||||
[]geometry.Point{
|
||||
details.oldObj.Center(),
|
||||
|
@ -176,6 +185,7 @@ func fenceMatch(
|
|||
o: details.obj,
|
||||
fields: details.fields,
|
||||
noLock: true,
|
||||
noTest: true,
|
||||
distance: distance,
|
||||
distOutput: fence.distance,
|
||||
})
|
||||
|
|
|
@ -33,6 +33,7 @@ type scanWriter struct {
|
|||
mu sync.Mutex
|
||||
s *Server
|
||||
wr *bytes.Buffer
|
||||
key string
|
||||
msg *Message
|
||||
col *collection.Collection
|
||||
fmap map[string]int
|
||||
|
@ -58,6 +59,8 @@ type scanWriter struct {
|
|||
values []resp.Value
|
||||
matchValues bool
|
||||
respOut resp.Value
|
||||
orgWheres []whereT
|
||||
orgWhereins []whereinT
|
||||
}
|
||||
|
||||
// ScanWriterParams ...
|
||||
|
@ -68,6 +71,7 @@ type ScanWriterParams struct {
|
|||
distance float64
|
||||
distOutput bool // query or fence requested distance output
|
||||
noLock bool
|
||||
noTest bool
|
||||
ignoreGlobMatch bool
|
||||
clip geojson.Object
|
||||
skipTesting bool
|
||||
|
@ -96,6 +100,7 @@ func (s *Server) newScanWriter(
|
|||
sw := &scanWriter{
|
||||
s: s,
|
||||
wr: wr,
|
||||
key: key,
|
||||
msg: msg,
|
||||
limit: limit,
|
||||
cursor: cursor,
|
||||
|
@ -113,34 +118,48 @@ func (s *Server) newScanWriter(
|
|||
sw.globSingle = true
|
||||
}
|
||||
}
|
||||
sw.col = s.getCol(key)
|
||||
sw.orgWheres = wheres
|
||||
sw.orgWhereins = whereins
|
||||
sw.loadWheres()
|
||||
return sw, nil
|
||||
}
|
||||
|
||||
func (sw *scanWriter) loadWheres() {
|
||||
sw.fmap = nil
|
||||
sw.farr = nil
|
||||
sw.wheres = nil
|
||||
sw.whereins = nil
|
||||
sw.fvals = nil
|
||||
sw.col = sw.s.getCol(sw.key)
|
||||
if sw.col != nil {
|
||||
sw.fmap = sw.col.FieldMap()
|
||||
sw.farr = sw.col.FieldArr()
|
||||
// This fills index value in wheres/whereins
|
||||
// so we don't have to map string field names for each tested object
|
||||
var ok bool
|
||||
if len(wheres) > 0 {
|
||||
sw.wheres = make([]whereT, len(wheres))
|
||||
for i, where := range wheres {
|
||||
if len(sw.orgWheres) > 0 {
|
||||
sw.wheres = make([]whereT, len(sw.orgWheres))
|
||||
for i, where := range sw.orgWheres {
|
||||
if where.index, ok = sw.fmap[where.field]; !ok {
|
||||
where.index = math.MaxInt32
|
||||
}
|
||||
sw.wheres[i] = where
|
||||
}
|
||||
}
|
||||
if len(whereins) > 0 {
|
||||
sw.whereins = make([]whereinT, len(whereins))
|
||||
for i, wherein := range whereins {
|
||||
if len(sw.orgWhereins) > 0 {
|
||||
sw.whereins = make([]whereinT, len(sw.orgWhereins))
|
||||
for i, wherein := range sw.orgWhereins {
|
||||
if wherein.index, ok = sw.fmap[wherein.field]; !ok {
|
||||
wherein.index = math.MaxInt32
|
||||
}
|
||||
sw.whereins[i] = wherein
|
||||
}
|
||||
}
|
||||
if len(sw.farr) > 0 {
|
||||
sw.fvals = make([]float64, len(sw.farr))
|
||||
}
|
||||
}
|
||||
sw.fvals = make([]float64, len(sw.farr))
|
||||
return sw, nil
|
||||
|
||||
}
|
||||
|
||||
func (sw *scanWriter) hasFieldsOutput() bool {
|
||||
|
@ -373,9 +392,14 @@ func (sw *scanWriter) writeObject(opts ScanWriterParams) bool {
|
|||
sw.mu.Lock()
|
||||
defer sw.mu.Unlock()
|
||||
}
|
||||
ok, keepGoing, _ := sw.testObject(opts.id, opts.o, opts.fields)
|
||||
if !ok {
|
||||
return keepGoing
|
||||
|
||||
keepGoing := true
|
||||
if !opts.noTest {
|
||||
var ok bool
|
||||
ok, keepGoing, _ = sw.testObject(opts.id, opts.o, opts.fields)
|
||||
if !ok {
|
||||
return keepGoing
|
||||
}
|
||||
}
|
||||
sw.count++
|
||||
if sw.output == outputCount {
|
||||
|
|
Loading…
Reference in New Issue