117 lines
2.5 KiB
Go
117 lines
2.5 KiB
Go
package qs
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/blevesearch/bleve"
|
|
"github.com/blevesearch/bleve/search/query"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// helper stuff for setting up range queries
|
|
|
|
// returns time, precision
|
|
// TODO: support other precisions? "YYYY-MM", "YYYY-MM-DDThh:mm:ss" etc?
|
|
func parseTime(in string, loc *time.Location) (time.Time, string) {
|
|
t, err := time.ParseInLocation("2006-01-02", in, loc)
|
|
if err != nil {
|
|
return time.Time{}, ""
|
|
}
|
|
return t, "day"
|
|
}
|
|
|
|
type rangeParams struct {
|
|
min, max *string
|
|
minInclusive, maxInclusive *bool
|
|
// need location for parsing times
|
|
loc *time.Location
|
|
}
|
|
|
|
func newRangeParams(minVal, maxVal string, minInc, maxInc bool, loc *time.Location) *rangeParams {
|
|
rp := &rangeParams{}
|
|
if minVal != "" {
|
|
rp.min = &minVal
|
|
rp.minInclusive = &minInc
|
|
}
|
|
if maxVal != "" {
|
|
rp.max = &maxVal
|
|
rp.maxInclusive = &maxInc
|
|
}
|
|
if loc == nil {
|
|
loc = time.UTC
|
|
}
|
|
rp.loc = loc
|
|
return rp
|
|
}
|
|
|
|
func (rp *rangeParams) numericArgs() (bool, *float64, *float64) {
|
|
var f1, f2 *float64
|
|
if rp.min != nil {
|
|
f, err := strconv.ParseFloat(*rp.min, 64)
|
|
if err != nil {
|
|
return false, nil, nil
|
|
}
|
|
f1 = &f
|
|
}
|
|
if rp.max != nil {
|
|
f, err := strconv.ParseFloat(*rp.max, 64)
|
|
if err != nil {
|
|
return false, nil, nil
|
|
}
|
|
f2 = &f
|
|
}
|
|
return true, f1, f2
|
|
}
|
|
|
|
func (rp *rangeParams) dateArgs() (bool, time.Time, time.Time) {
|
|
var truthy bool = true
|
|
var falsey bool = false
|
|
var t1, t2 time.Time
|
|
var prec string
|
|
if rp.min != nil {
|
|
t1, prec = parseTime(*rp.min, rp.loc)
|
|
switch prec {
|
|
case "day":
|
|
if !*rp.minInclusive {
|
|
// add 1 day and make inclusive
|
|
t1 = t1.AddDate(0, 0, 1)
|
|
rp.minInclusive = &truthy
|
|
}
|
|
default:
|
|
return false, t1, t2
|
|
}
|
|
}
|
|
if rp.max != nil {
|
|
t2, prec = parseTime(*rp.max, rp.loc)
|
|
switch prec {
|
|
case "day":
|
|
if *rp.maxInclusive {
|
|
// add 1 day and change to exclusive
|
|
t2 = t2.AddDate(0, 0, 1)
|
|
rp.maxInclusive = &falsey
|
|
}
|
|
default:
|
|
return false, t1, t2
|
|
}
|
|
}
|
|
|
|
return true, t1, t2
|
|
}
|
|
|
|
// try and build a query from the given params
|
|
func (rp *rangeParams) generate() (query.Query, error) {
|
|
if rp.min == nil && rp.max == nil {
|
|
return nil, fmt.Errorf("empty range")
|
|
}
|
|
isNumeric, f1, f2 := rp.numericArgs()
|
|
if isNumeric {
|
|
return bleve.NewNumericRangeInclusiveQuery(f1, f2, rp.minInclusive, rp.maxInclusive), nil
|
|
}
|
|
|
|
isDate, t1, t2 := rp.dateArgs()
|
|
if isDate {
|
|
return bleve.NewDateRangeInclusiveQuery(t1, t2, rp.minInclusive, rp.maxInclusive), nil
|
|
}
|
|
return nil, fmt.Errorf("not numeric")
|
|
|
|
}
|