mirror of https://github.com/tidwall/tile38.git
Refactor cursor/paging.
This commit is contained in:
parent
b94f3685b6
commit
0933c541f4
|
@ -309,10 +309,19 @@ func (c *Collection) FieldArr() []string {
|
||||||
|
|
||||||
// Scan iterates though the collection ids.
|
// Scan iterates though the collection ids.
|
||||||
func (c *Collection) Scan(desc bool,
|
func (c *Collection) Scan(desc bool,
|
||||||
|
offset uint64,
|
||||||
|
inc func(n uint64),
|
||||||
iterator func(id string, obj geojson.Object, fields []float64) bool,
|
iterator func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
var keepon = true
|
var keepon = true
|
||||||
|
var count uint64
|
||||||
|
inc(offset)
|
||||||
iter := func(key string, value interface{}) bool {
|
iter := func(key string, value interface{}) bool {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
inc(1)
|
||||||
iitm := value.(*itemT)
|
iitm := value.(*itemT)
|
||||||
keepon = iterator(iitm.id, iitm.obj, c.getFieldValues(iitm.id))
|
keepon = iterator(iitm.id, iitm.obj, c.getFieldValues(iitm.id))
|
||||||
return keepon
|
return keepon
|
||||||
|
@ -327,10 +336,19 @@ func (c *Collection) Scan(desc bool,
|
||||||
|
|
||||||
// ScanRange iterates though the collection starting with specified id.
|
// ScanRange iterates though the collection starting with specified id.
|
||||||
func (c *Collection) ScanRange(start, end string, desc bool,
|
func (c *Collection) ScanRange(start, end string, desc bool,
|
||||||
|
offset uint64,
|
||||||
|
inc func(n uint64),
|
||||||
iterator func(id string, obj geojson.Object, fields []float64) bool,
|
iterator func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
var keepon = true
|
var keepon = true
|
||||||
|
var count uint64
|
||||||
|
inc(offset)
|
||||||
iter := func(key string, value interface{}) bool {
|
iter := func(key string, value interface{}) bool {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
inc(1)
|
||||||
if !desc {
|
if !desc {
|
||||||
if key >= end {
|
if key >= end {
|
||||||
return false
|
return false
|
||||||
|
@ -355,10 +373,19 @@ func (c *Collection) ScanRange(start, end string, desc bool,
|
||||||
|
|
||||||
// SearchValues iterates though the collection values.
|
// SearchValues iterates though the collection values.
|
||||||
func (c *Collection) SearchValues(desc bool,
|
func (c *Collection) SearchValues(desc bool,
|
||||||
|
offset uint64,
|
||||||
|
inc func(n uint64),
|
||||||
iterator func(id string, obj geojson.Object, fields []float64) bool,
|
iterator func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
var keepon = true
|
var keepon = true
|
||||||
|
var count uint64
|
||||||
|
inc(offset)
|
||||||
iter := func(item btree.Item) bool {
|
iter := func(item btree.Item) bool {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
inc(1)
|
||||||
iitm := item.(*itemT)
|
iitm := item.(*itemT)
|
||||||
keepon = iterator(iitm.id, iitm.obj, c.getFieldValues(iitm.id))
|
keepon = iterator(iitm.id, iitm.obj, c.getFieldValues(iitm.id))
|
||||||
return keepon
|
return keepon
|
||||||
|
@ -373,10 +400,19 @@ func (c *Collection) SearchValues(desc bool,
|
||||||
|
|
||||||
// SearchValuesRange iterates though the collection values.
|
// SearchValuesRange iterates though the collection values.
|
||||||
func (c *Collection) SearchValuesRange(start, end string, desc bool,
|
func (c *Collection) SearchValuesRange(start, end string, desc bool,
|
||||||
|
offset uint64,
|
||||||
|
inc func(n uint64),
|
||||||
iterator func(id string, obj geojson.Object, fields []float64) bool,
|
iterator func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
var keepon = true
|
var keepon = true
|
||||||
|
var count uint64
|
||||||
|
inc(offset)
|
||||||
iter := func(item btree.Item) bool {
|
iter := func(item btree.Item) bool {
|
||||||
|
count++
|
||||||
|
if count <= offset {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
inc(1)
|
||||||
iitm := item.(*itemT)
|
iitm := item.(*itemT)
|
||||||
keepon = iterator(iitm.id, iitm.obj, c.getFieldValues(iitm.id))
|
keepon = iterator(iitm.id, iitm.obj, c.getFieldValues(iitm.id))
|
||||||
return keepon
|
return keepon
|
||||||
|
@ -500,9 +536,11 @@ func (c *Collection) Within(
|
||||||
obj geojson.Object,
|
obj geojson.Object,
|
||||||
offset uint64,
|
offset uint64,
|
||||||
sparse uint8,
|
sparse uint8,
|
||||||
|
inc func(n uint64),
|
||||||
iter func(id string, obj geojson.Object, fields []float64) bool,
|
iter func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
var count uint64
|
var count uint64
|
||||||
|
inc(offset)
|
||||||
if sparse > 0 {
|
if sparse > 0 {
|
||||||
return c.geoSparse(obj, sparse,
|
return c.geoSparse(obj, sparse,
|
||||||
func(id string, o geojson.Object, fields []float64) (
|
func(id string, o geojson.Object, fields []float64) (
|
||||||
|
@ -512,6 +550,7 @@ func (c *Collection) Within(
|
||||||
if count <= offset {
|
if count <= offset {
|
||||||
return false, true
|
return false, true
|
||||||
}
|
}
|
||||||
|
inc(1)
|
||||||
if match = o.Within(obj); match {
|
if match = o.Within(obj); match {
|
||||||
ok = iter(id, o, fields)
|
ok = iter(id, o, fields)
|
||||||
}
|
}
|
||||||
|
@ -525,6 +564,7 @@ func (c *Collection) Within(
|
||||||
if count <= offset {
|
if count <= offset {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
inc(1)
|
||||||
if o.Within(obj) {
|
if o.Within(obj) {
|
||||||
return iter(id, o, fields)
|
return iter(id, o, fields)
|
||||||
}
|
}
|
||||||
|
@ -539,9 +579,11 @@ func (c *Collection) Intersects(
|
||||||
obj geojson.Object,
|
obj geojson.Object,
|
||||||
offset uint64,
|
offset uint64,
|
||||||
sparse uint8,
|
sparse uint8,
|
||||||
|
inc func(n uint64),
|
||||||
iter func(id string, obj geojson.Object, fields []float64) bool,
|
iter func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
var count uint64
|
var count uint64
|
||||||
|
inc(offset)
|
||||||
if sparse > 0 {
|
if sparse > 0 {
|
||||||
return c.geoSparse(obj, sparse,
|
return c.geoSparse(obj, sparse,
|
||||||
func(id string, o geojson.Object, fields []float64) (
|
func(id string, o geojson.Object, fields []float64) (
|
||||||
|
@ -551,6 +593,7 @@ func (c *Collection) Intersects(
|
||||||
if count <= offset {
|
if count <= offset {
|
||||||
return false, true
|
return false, true
|
||||||
}
|
}
|
||||||
|
inc(1)
|
||||||
if match = o.Intersects(obj); match {
|
if match = o.Intersects(obj); match {
|
||||||
ok = iter(id, o, fields)
|
ok = iter(id, o, fields)
|
||||||
}
|
}
|
||||||
|
@ -564,6 +607,7 @@ func (c *Collection) Intersects(
|
||||||
if count <= offset {
|
if count <= offset {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
inc(1)
|
||||||
if o.Intersects(obj) {
|
if o.Intersects(obj) {
|
||||||
return iter(id, o, fields)
|
return iter(id, o, fields)
|
||||||
}
|
}
|
||||||
|
@ -576,11 +620,13 @@ func (c *Collection) Intersects(
|
||||||
func (c *Collection) Nearby(
|
func (c *Collection) Nearby(
|
||||||
target geojson.Object,
|
target geojson.Object,
|
||||||
offset uint64,
|
offset uint64,
|
||||||
|
inc func(n uint64),
|
||||||
iter func(id string, obj geojson.Object, fields []float64) bool,
|
iter func(id string, obj geojson.Object, fields []float64) bool,
|
||||||
) bool {
|
) bool {
|
||||||
alive := true
|
alive := true
|
||||||
center := target.Center()
|
center := target.Center()
|
||||||
var count uint64
|
var count uint64
|
||||||
|
inc(offset)
|
||||||
c.index.Nearby(
|
c.index.Nearby(
|
||||||
[]float64{center.X, center.Y},
|
[]float64{center.X, center.Y},
|
||||||
[]float64{center.X, center.Y},
|
[]float64{center.X, center.Y},
|
||||||
|
@ -589,6 +635,7 @@ func (c *Collection) Nearby(
|
||||||
if count <= offset {
|
if count <= offset {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
inc(1)
|
||||||
item := itemv.(*itemT)
|
item := itemv.(*itemT)
|
||||||
alive = iter(item.id, item.obj, c.getFieldValues(item.id))
|
alive = iter(item.id, item.obj, c.getFieldValues(item.id))
|
||||||
return alive
|
return alive
|
||||||
|
|
|
@ -372,9 +372,9 @@ func (server *Server) cmdPdel(msg *Message) (res resp.Value, d commandDetailsT,
|
||||||
if col != nil {
|
if col != nil {
|
||||||
g := glob.Parse(d.pattern, false)
|
g := glob.Parse(d.pattern, false)
|
||||||
if g.Limits[0] == "" && g.Limits[1] == "" {
|
if g.Limits[0] == "" && g.Limits[1] == "" {
|
||||||
col.Scan(false, iter)
|
col.Scan(false, 0, func(n uint64) {}, iter)
|
||||||
} else {
|
} else {
|
||||||
col.ScanRange(g.Limits[0], g.Limits[1], false, iter)
|
col.ScanRange(g.Limits[0], g.Limits[1], false, 0, func(n uint64) {}, iter)
|
||||||
}
|
}
|
||||||
var atLeastOneNotDeleted bool
|
var atLeastOneNotDeleted bool
|
||||||
for i, dc := range d.children {
|
for i, dc := range d.children {
|
||||||
|
|
|
@ -299,10 +299,10 @@ func extendRoamMessage(
|
||||||
}
|
}
|
||||||
g := glob.Parse(pattern, false)
|
g := glob.Parse(pattern, false)
|
||||||
if g.Limits[0] == "" && g.Limits[1] == "" {
|
if g.Limits[0] == "" && g.Limits[1] == "" {
|
||||||
col.Scan(false, iterator)
|
col.Scan(false, 0, func(n uint64) {}, iterator)
|
||||||
} else {
|
} else {
|
||||||
col.ScanRange(g.Limits[0], g.Limits[1],
|
col.ScanRange(g.Limits[0], g.Limits[1],
|
||||||
false, iterator)
|
false, 0, func(n uint64) {}, iterator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nmsg = append(nmsg, ']')
|
nmsg = append(nmsg, ']')
|
||||||
|
@ -364,7 +364,7 @@ func fenceMatchRoam(
|
||||||
prevNearbys := fence.roam.nearbys[tid]
|
prevNearbys := fence.roam.nearbys[tid]
|
||||||
var newNearbys map[string]bool
|
var newNearbys map[string]bool
|
||||||
|
|
||||||
col.Intersects(obj, 0, 0, func(
|
col.Intersects(obj, 0, 0, func(n uint64) {}, func(
|
||||||
id string, obj2 geojson.Object, fields []float64,
|
id string, obj2 geojson.Object, fields []float64,
|
||||||
) bool {
|
) bool {
|
||||||
if c.hasExpired(fence.roam.key, id) {
|
if c.hasExpired(fence.roam.key, id) {
|
||||||
|
|
|
@ -66,7 +66,7 @@ func (c *Server) cmdScan(msg *Message) (res resp.Value, err error) {
|
||||||
} else {
|
} else {
|
||||||
g := glob.Parse(sw.globPattern, s.desc)
|
g := glob.Parse(sw.globPattern, s.desc)
|
||||||
if g.Limits[0] == "" && g.Limits[1] == "" {
|
if g.Limits[0] == "" && g.Limits[1] == "" {
|
||||||
sw.col.Scan(s.desc,
|
sw.col.Scan(s.desc, s.cursor, sw.IncCursor,
|
||||||
func(id string, o geojson.Object, fields []float64) bool {
|
func(id string, o geojson.Object, fields []float64) bool {
|
||||||
return sw.writeObject(ScanWriterParams{
|
return sw.writeObject(ScanWriterParams{
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -76,7 +76,7 @@ func (c *Server) cmdScan(msg *Message) (res resp.Value, err error) {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
sw.col.ScanRange(g.Limits[0], g.Limits[1], s.desc,
|
sw.col.ScanRange(g.Limits[0], g.Limits[1], s.desc, s.cursor, sw.IncCursor,
|
||||||
func(id string, o geojson.Object, fields []float64) bool {
|
func(id string, o geojson.Object, fields []float64) bool {
|
||||||
return sw.writeObject(ScanWriterParams{
|
return sw.writeObject(ScanWriterParams{
|
||||||
id: id,
|
id: id,
|
||||||
|
|
|
@ -42,6 +42,7 @@ type scanWriter struct {
|
||||||
wheres []whereT
|
wheres []whereT
|
||||||
whereins []whereinT
|
whereins []whereinT
|
||||||
whereevals []whereevalT
|
whereevals []whereevalT
|
||||||
|
numberIters uint64
|
||||||
numberItems uint64
|
numberItems uint64
|
||||||
nofields bool
|
nofields bool
|
||||||
cursor uint64
|
cursor uint64
|
||||||
|
@ -166,7 +167,7 @@ func (sw *scanWriter) writeHead() {
|
||||||
func (sw *scanWriter) writeFoot() {
|
func (sw *scanWriter) writeFoot() {
|
||||||
sw.mu.Lock()
|
sw.mu.Lock()
|
||||||
defer sw.mu.Unlock()
|
defer sw.mu.Unlock()
|
||||||
cursor := sw.cursor + sw.numberItems
|
cursor := sw.numberIters
|
||||||
if !sw.hitLimit {
|
if !sw.hitLimit {
|
||||||
cursor = 0
|
cursor = 0
|
||||||
}
|
}
|
||||||
|
@ -325,6 +326,11 @@ func (sw *scanWriter) globMatch(id string, o geojson.Object) (ok, keepGoing bool
|
||||||
return true, true
|
return true, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increment cursor
|
||||||
|
func (sw *scanWriter) IncCursor(n uint64) {
|
||||||
|
sw.numberIters += n
|
||||||
|
}
|
||||||
|
|
||||||
// ok is whether the object passes the test and should be written
|
// ok is whether the object passes the test and should be written
|
||||||
// keepGoing is whether there could be more objects to test
|
// keepGoing is whether there could be more objects to test
|
||||||
func (sw *scanWriter) testObject(id string, o geojson.Object, fields []float64, ignoreGlobMatch bool) (
|
func (sw *scanWriter) testObject(id string, o geojson.Object, fields []float64, ignoreGlobMatch bool) (
|
||||||
|
|
|
@ -410,7 +410,7 @@ func (server *Server) nearestNeighbors(
|
||||||
maxDist := target.Haversine()
|
maxDist := target.Haversine()
|
||||||
limit := int(sw.limit)
|
limit := int(sw.limit)
|
||||||
var items []iterItem
|
var items []iterItem
|
||||||
sw.col.Nearby(target, sw.cursor, func(id string, o geojson.Object, fields []float64) bool {
|
sw.col.Nearby(target, sw.cursor, sw.IncCursor, func(id string, o geojson.Object, fields []float64) bool {
|
||||||
if server.hasExpired(s.key, id) {
|
if server.hasExpired(s.key, id) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -481,7 +481,7 @@ func (server *Server) cmdWithinOrIntersects(cmd string, msg *Message) (res resp.
|
||||||
sw.writeHead()
|
sw.writeHead()
|
||||||
if sw.col != nil {
|
if sw.col != nil {
|
||||||
if cmd == "within" {
|
if cmd == "within" {
|
||||||
sw.col.Within(s.obj, s.cursor, s.sparse, func(
|
sw.col.Within(s.obj, s.cursor, s.sparse, sw.IncCursor, func(
|
||||||
id string, o geojson.Object, fields []float64,
|
id string, o geojson.Object, fields []float64,
|
||||||
) bool {
|
) bool {
|
||||||
if server.hasExpired(s.key, id) {
|
if server.hasExpired(s.key, id) {
|
||||||
|
@ -495,7 +495,7 @@ func (server *Server) cmdWithinOrIntersects(cmd string, msg *Message) (res resp.
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else if cmd == "intersects" {
|
} else if cmd == "intersects" {
|
||||||
sw.col.Intersects(s.obj, s.cursor, s.sparse, func(
|
sw.col.Intersects(s.obj, s.cursor, s.sparse, sw.IncCursor, func(
|
||||||
id string,
|
id string,
|
||||||
o geojson.Object,
|
o geojson.Object,
|
||||||
fields []float64,
|
fields []float64,
|
||||||
|
@ -579,7 +579,7 @@ func (server *Server) cmdSearch(msg *Message) (res resp.Value, err error) {
|
||||||
} else {
|
} else {
|
||||||
g := glob.Parse(sw.globPattern, s.desc)
|
g := glob.Parse(sw.globPattern, s.desc)
|
||||||
if g.Limits[0] == "" && g.Limits[1] == "" {
|
if g.Limits[0] == "" && g.Limits[1] == "" {
|
||||||
sw.col.SearchValues(s.desc,
|
sw.col.SearchValues(s.desc, s.cursor, sw.IncCursor,
|
||||||
func(id string, o geojson.Object, fields []float64) bool {
|
func(id string, o geojson.Object, fields []float64) bool {
|
||||||
return sw.writeObject(ScanWriterParams{
|
return sw.writeObject(ScanWriterParams{
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -593,7 +593,7 @@ func (server *Server) cmdSearch(msg *Message) (res resp.Value, err error) {
|
||||||
// must disable globSingle for string value type matching because
|
// must disable globSingle for string value type matching because
|
||||||
// globSingle is only for ID matches, not values.
|
// globSingle is only for ID matches, not values.
|
||||||
sw.globSingle = false
|
sw.globSingle = false
|
||||||
sw.col.SearchValuesRange(g.Limits[0], g.Limits[1], s.desc,
|
sw.col.SearchValuesRange(g.Limits[0], g.Limits[1], s.desc, s.cursor, sw.IncCursor,
|
||||||
func(id string, o geojson.Object, fields []float64) bool {
|
func(id string, o geojson.Object, fields []float64) bool {
|
||||||
return sw.writeObject(ScanWriterParams{
|
return sw.writeObject(ScanWriterParams{
|
||||||
id: id,
|
id: id,
|
||||||
|
|
|
@ -6,10 +6,15 @@ import (
|
||||||
|
|
||||||
func subTestSearch(t *testing.T, mc *mockServer) {
|
func subTestSearch(t *testing.T, mc *mockServer) {
|
||||||
runStep(t, mc, "KNN", keys_KNN_test)
|
runStep(t, mc, "KNN", keys_KNN_test)
|
||||||
|
runStep(t, mc, "KNN_CURSOR", keys_KNN_cursor_test)
|
||||||
runStep(t, mc, "WITHIN_CIRCLE", keys_WITHIN_CIRCLE_test)
|
runStep(t, mc, "WITHIN_CIRCLE", keys_WITHIN_CIRCLE_test)
|
||||||
runStep(t, mc, "INTERSECTS_CIRCLE", keys_INTERSECTS_CIRCLE_test)
|
runStep(t, mc, "INTERSECTS_CIRCLE", keys_INTERSECTS_CIRCLE_test)
|
||||||
runStep(t, mc, "WITHIN", keys_WITHIN_test)
|
runStep(t, mc, "WITHIN", keys_WITHIN_test)
|
||||||
|
runStep(t, mc, "WITHIN_CURSOR", keys_WITHIN_CURSOR_test)
|
||||||
runStep(t, mc, "INTERSECTS", keys_INTERSECTS_test)
|
runStep(t, mc, "INTERSECTS", keys_INTERSECTS_test)
|
||||||
|
runStep(t, mc, "INTERSECTS_CURSOR", keys_INTERSECTS_CURSOR_test)
|
||||||
|
runStep(t, mc, "SCAN_CURSOR", keys_SCAN_CURSOR_test)
|
||||||
|
runStep(t, mc, "SEARCH_CURSOR", keys_SEARCH_CURSOR_test)
|
||||||
}
|
}
|
||||||
|
|
||||||
func keys_KNN_test(mc *mockServer) error {
|
func keys_KNN_test(mc *mockServer) error {
|
||||||
|
@ -26,6 +31,28 @@ func keys_KNN_test(mc *mockServer) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func keys_KNN_cursor_test(mc *mockServer) error {
|
||||||
|
return mc.DoBatch([][]interface{}{
|
||||||
|
{"SET", "mykey", "1", "FIELD", "foo", 5.5, "POINT", 5, 5}, {"OK"},
|
||||||
|
{"SET", "mykey", "2", "FIELD", "foo", 19.19, "POINT",19, 19}, {"OK"},
|
||||||
|
{"SET", "mykey", "3", "FIELD", "foo", 12.19, "POINT", 12, 19}, {"OK"},
|
||||||
|
{"SET", "mykey", "4", "FIELD", "foo", -5.5, "POINT", -5, 5}, {"OK"},
|
||||||
|
{"SET", "mykey", "5", "FIELD", "foo", 13.21, "POINT", 33, 21}, {"OK"},
|
||||||
|
{"NEARBY", "mykey", "LIMIT", 2, "POINTS", "POINT", 20, 20}, {
|
||||||
|
"[2 [[2 [19 19] [foo 19.19]] [3 [12 19] [foo 12.19]]]]"},
|
||||||
|
{"NEARBY", "mykey", "CURSOR", 2, "LIMIT", 1, "POINTS", "POINT", 20, 20}, {
|
||||||
|
"[3 [[5 [33 21] [foo 13.21]]]]"},
|
||||||
|
{"NEARBY", "mykey", "LIMIT", 2, "WHERE", "foo", -10, 15, "POINTS", "POINT", 20, 20}, {
|
||||||
|
"[3 [[3 [12 19] [foo 12.19]] [5 [33 21] [foo 13.21]]]]"},
|
||||||
|
{"NEARBY", "mykey", "CURSOR", 3, "LIMIT", 1, "WHERE", "foo", -10, 15, "POINTS", "POINT", 20, 20}, {
|
||||||
|
"[4 [[1 [5 5] [foo 5.5]]]]"},
|
||||||
|
{"NEARBY", "mykey", "CURSOR", 4, "LIMIT", 1, "WHERE", "foo", -10, 15, "POINTS", "POINT", 20, 20}, {
|
||||||
|
"[5 [[4 [-5 5] [foo -5.5]]]]"},
|
||||||
|
{"NEARBY", "mykey", "CURSOR", 4, "LIMIT", 10, "WHERE", "foo", -10, 15, "POINTS", "POINT", 20, 20}, {
|
||||||
|
"[0 [[4 [-5 5] [foo -5.5]]]]"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func keys_WITHIN_test(mc *mockServer) error {
|
func keys_WITHIN_test(mc *mockServer) error {
|
||||||
return mc.DoBatch([][]interface{}{
|
return mc.DoBatch([][]interface{}{
|
||||||
{"SET", "mykey", "point1", "POINT", 37.7335, -122.4412}, {"OK"},
|
{"SET", "mykey", "point1", "POINT", 37.7335, -122.4412}, {"OK"},
|
||||||
|
@ -73,6 +100,44 @@ func keys_WITHIN_test(mc *mockServer) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func keys_WITHIN_CURSOR_test(mc *mockServer) error {
|
||||||
|
testArea := `{
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[-122.44126439094543,37.72906137107],
|
||||||
|
[-122.43980526924135,37.72906137107],
|
||||||
|
[-122.43980526924135,37.73421283683962],
|
||||||
|
[-122.44126439094543,37.73421283683962],
|
||||||
|
[-122.44126439094543,37.72906137107]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
return mc.DoBatch([][]interface{}{
|
||||||
|
{"SET", "mykey", "point1", "FIELD", "foo", 1, "POINT", 37.7335, -122.4412}, {"OK"},
|
||||||
|
{"SET", "mykey", "point2", "FIELD", "foo", 2, "POINT", 37.7335, -122.44121}, {"OK"},
|
||||||
|
{"SET", "mykey", "line3", "FIELD", "foo", 3, "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
|
||||||
|
{"SET", "mykey", "poly4", "FIELD", "foo", 4, "OBJECT", `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]]}`}, {"OK"},
|
||||||
|
{"SET", "mykey", "multipoly5","FIELD", "foo", 5, "OBJECT", `{"type":"MultiPolygon","coordinates":[[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]],[[[-122.44091033935547,37.731981251280985],[-122.43994474411011,37.731981251280985],[-122.43994474411011,37.73254976045042],[-122.44091033935547,37.73254976045042],[-122.44091033935547,37.731981251280985]]]]}`}, {"OK"},
|
||||||
|
{"SET", "mykey", "point6", "FIELD", "foo", 6, "POINT", -5, 5}, {"OK"},
|
||||||
|
{"SET", "mykey", "point7", "FIELD", "foo", 7, "POINT", 33, 21}, {"OK"},
|
||||||
|
{"SET", "mykey", "poly8", "FIELD", "foo", 8, "OBJECT", `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]],[[-122.44060993194579,37.73345766902749],[-122.44044363498686,37.73345766902749],[-122.44044363498686,37.73355524732416],[-122.44060993194579,37.73355524732416],[-122.44060993194579,37.73345766902749]],[[-122.44060724973677,37.7336888869566],[-122.4402102828026,37.7336888869566],[-122.4402102828026,37.7339752567853],[-122.44060724973677,37.7339752567853],[-122.44060724973677,37.7336888869566]]]}`}, {"OK"},
|
||||||
|
{"SET", "mykey", "point9", "FIELD", "foo", 9, "POINT", 37.7335, -122.4412}, {"OK"},
|
||||||
|
{"WITHIN", "mykey", "LIMIT", 3, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[3 [point1 point2 line3]]"},
|
||||||
|
{"WITHIN", "mykey", "CURSOR", 3, "LIMIT", 3, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[6 [poly4 multipoly5 poly8]]"},
|
||||||
|
{"WITHIN", "mykey", "WHERE", "foo", 3, 5, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[0 [line3 poly4 multipoly5]]"},
|
||||||
|
{"WITHIN", "mykey", "LIMIT", 1, "WHERE", "foo", 3, 5, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[3 [line3]]"},
|
||||||
|
{"WITHIN", "mykey", "CURSOR", 3, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[6 [poly8]]"},
|
||||||
|
{"WITHIN", "mykey", "CURSOR", 6, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[7 [point9]]"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func keys_INTERSECTS_test(mc *mockServer) error {
|
func keys_INTERSECTS_test(mc *mockServer) error {
|
||||||
return mc.DoBatch([][]interface{}{
|
return mc.DoBatch([][]interface{}{
|
||||||
{"SET", "mykey", "point1", "POINT", 37.7335, -122.4412}, {"OK"},
|
{"SET", "mykey", "point1", "POINT", 37.7335, -122.4412}, {"OK"},
|
||||||
|
@ -123,6 +188,44 @@ func keys_INTERSECTS_test(mc *mockServer) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func keys_INTERSECTS_CURSOR_test(mc *mockServer) error {
|
||||||
|
testArea := `{
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[-122.44126439094543,37.732906137107],
|
||||||
|
[-122.43980526924135,37.732906137107],
|
||||||
|
[-122.43980526924135,37.73421283683962],
|
||||||
|
[-122.44126439094543,37.73421283683962],
|
||||||
|
[-122.44126439094543,37.732906137107]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
return mc.DoBatch([][]interface{}{
|
||||||
|
{"SET", "mykey", "point1", "FIELD", "foo", 1, "POINT", 37.7335, -122.4412}, {"OK"},
|
||||||
|
{"SET", "mykey", "point2", "FIELD", "foo", 2, "POINT", 37.7335, -122.44121}, {"OK"},
|
||||||
|
{"SET", "mykey", "line3", "FIELD", "foo", 3, "OBJECT", `{"type":"LineString","coordinates":[[-122.4408378,37.7341129],[-122.4408378,37.733]]}`}, {"OK"},
|
||||||
|
{"SET", "mykey", "poly4", "FIELD", "foo", 4, "OBJECT", `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]]}`}, {"OK"},
|
||||||
|
{"SET", "mykey", "multipoly5", "FIELD", "foo", 5, "OBJECT", `{"type":"MultiPolygon","coordinates":[[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]]],[[[-122.44091033935547,37.731981251280985],[-122.43994474411011,37.731981251280985],[-122.43994474411011,37.73254976045042],[-122.44091033935547,37.73254976045042],[-122.44091033935547,37.731981251280985]]]]}`}, {"OK"},
|
||||||
|
{"SET", "mykey", "point6", "FIELD", "foo", 6, "POINT", -5, 5}, {"OK"},
|
||||||
|
{"SET", "mykey", "point7", "FIELD", "foo", 7, "POINT", 33, 21}, {"OK"},
|
||||||
|
{"SET", "mykey", "poly8", "FIELD", "foo", 8, "OBJECT", `{"type":"Polygon","coordinates":[[[-122.4408378,37.7341129],[-122.4408378,37.733],[-122.44,37.733],[-122.44,37.7341129],[-122.4408378,37.7341129]],[[-122.44060993194579,37.73345766902749],[-122.44044363498686,37.73345766902749],[-122.44044363498686,37.73355524732416],[-122.44060993194579,37.73355524732416],[-122.44060993194579,37.73345766902749]],[[-122.44060724973677,37.7336888869566],[-122.4402102828026,37.7336888869566],[-122.4402102828026,37.7339752567853],[-122.44060724973677,37.7339752567853],[-122.44060724973677,37.7336888869566]]]}`}, {"OK"},
|
||||||
|
{"SET", "mykey", "point9", "FIELD", "foo", 9, "POINT", 37.7335, -122.4412}, {"OK"},
|
||||||
|
{"INTERSECTS", "mykey", "LIMIT", 3, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[3 [point1 point2 line3]]"},
|
||||||
|
{"INTERSECTS", "mykey", "CURSOR", 3, "LIMIT", 3, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[6 [poly4 multipoly5 poly8]]"},
|
||||||
|
{"INTERSECTS", "mykey", "WHERE", "foo", 3, 5, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[0 [line3 poly4 multipoly5]]"},
|
||||||
|
{"INTERSECTS", "mykey", "LIMIT", 1, "WHERE", "foo", 3, 5, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[3 [line3]]"},
|
||||||
|
{"INTERSECTS", "mykey", "CURSOR", 3, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[6 [poly8]]"},
|
||||||
|
{"INTERSECTS", "mykey", "CURSOR", 6, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS", "OBJECT", testArea}, {
|
||||||
|
"[7 [point9]]"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func keys_WITHIN_CIRCLE_test(mc *mockServer) error {
|
func keys_WITHIN_CIRCLE_test(mc *mockServer) error {
|
||||||
return mc.DoBatch([][]interface{}{
|
return mc.DoBatch([][]interface{}{
|
||||||
{"SET", "mykey", "1", "POINT", 37.7335, -122.4412}, {"OK"},
|
{"SET", "mykey", "1", "POINT", 37.7335, -122.4412}, {"OK"},
|
||||||
|
@ -154,3 +257,48 @@ func keys_INTERSECTS_CIRCLE_test(mc *mockServer) error {
|
||||||
"[0 [1 2]]"},
|
"[0 [1 2]]"},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func keys_SCAN_CURSOR_test(mc *mockServer) error {
|
||||||
|
return mc.DoBatch([][]interface{}{
|
||||||
|
{"SET", "mykey", "id1", "FIELD", "foo", 1, "STRING", "bar1"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id2", "FIELD", "foo", 2, "STRING", "bar2"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id3", "FIELD", "foo", 3, "STRING", "bar3"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id4", "FIELD", "foo", 4, "STRING", "bar4"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id5", "FIELD", "foo", 5, "STRING", "bar5"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id6", "FIELD", "foo", 6, "STRING", "bar6"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id7", "FIELD", "foo", 7, "STRING", "bar7"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id8", "FIELD", "foo", 8, "STRING", "bar8"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id9", "FIELD", "foo", 9, "STRING", "bar9"}, {"OK"},
|
||||||
|
{"SCAN", "mykey", "LIMIT", 3, "IDS"}, {"[3 [id1 id2 id3]]"},
|
||||||
|
{"SCAN", "mykey", "CURSOR", 3, "LIMIT", 3, "IDS"}, {"[6 [id4 id5 id6]]"},
|
||||||
|
{"SCAN", "mykey", "WHERE", "foo", 3, 5, "IDS"}, {"[0 [id3 id4 id5]]"},
|
||||||
|
{"SCAN", "mykey", "LIMIT", 1, "WHERE", "foo", 3, 5, "IDS"}, {"[3 [id3]]"},
|
||||||
|
{"SCAN", "mykey", "CURSOR", 3, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS"}, {
|
||||||
|
"[8 [id8]]"},
|
||||||
|
{"SCAN", "mykey", "CURSOR", 6, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS"}, {
|
||||||
|
"[8 [id8]]"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func keys_SEARCH_CURSOR_test(mc *mockServer) error {
|
||||||
|
return mc.DoBatch([][]interface{}{
|
||||||
|
{"SET", "mykey", "id1", "FIELD", "foo", 1, "STRING", "bar1"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id2", "FIELD", "foo", 2, "STRING", "bar2"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id3", "FIELD", "foo", 3, "STRING", "bar3"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id4", "FIELD", "foo", 4, "STRING", "bar4"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id5", "FIELD", "foo", 5, "STRING", "bar5"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id6", "FIELD", "foo", 6, "STRING", "bar6"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id7", "FIELD", "foo", 7, "STRING", "bar7"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id8", "FIELD", "foo", 8, "STRING", "bar8"}, {"OK"},
|
||||||
|
{"SET", "mykey", "id9", "FIELD", "foo", 9, "STRING", "bar9"}, {"OK"},
|
||||||
|
{"SEARCH", "mykey", "LIMIT", 3, "IDS"}, {"[3 [id1 id2 id3]]"},
|
||||||
|
{"SEARCH", "mykey", "CURSOR", 3, "LIMIT", 3, "IDS"}, {"[6 [id4 id5 id6]]"},
|
||||||
|
{"SEARCH", "mykey", "WHERE", "foo", 3, 5, "IDS"}, {"[0 [id3 id4 id5]]"},
|
||||||
|
{"SEARCH", "mykey", "LIMIT", 1, "WHERE", "foo", 3, 5, "IDS"}, {"[3 [id3]]"},
|
||||||
|
{"SEARCH", "mykey", "CURSOR", 3, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS"}, {
|
||||||
|
"[8 [id8]]"},
|
||||||
|
{"SEARCH", "mykey", "CURSOR", 6, "LIMIT", 1, "WHERE", "foo", 8, 9, "IDS"}, {
|
||||||
|
"[8 [id8]]"},
|
||||||
|
{"SEARCH", "mykey", "LIMIT", 3, "DESC", "IDS"}, {"[3 [id9 id8 id7]]"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue