mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-18 05:35:10 +00:00
Search API (#350)
This commit is contained in:
101
search/handler/parser.go
Normal file
101
search/handler/parser.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/bitly/go-simplejson"
|
||||
)
|
||||
|
||||
func parseQueryString(query string) (*simplejson.Json, error) {
|
||||
_, items := lex("foo", query)
|
||||
res, err := parseQueryStringRec(items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
js := simplejson.New()
|
||||
js.Set("query", res)
|
||||
return js, nil
|
||||
}
|
||||
|
||||
const (
|
||||
matchTypeRange = "range"
|
||||
matchTypeMatch = "match"
|
||||
matchTypeWildcard = "wildcard"
|
||||
)
|
||||
|
||||
func parseQueryStringRec(items chan item) (*simplejson.Json, error) {
|
||||
retTerm := simplejson.New()
|
||||
currFieldName := ""
|
||||
currBool := ""
|
||||
currMatchType := matchTypeMatch
|
||||
currPathAddition := ""
|
||||
terms := []*simplejson.Json{}
|
||||
itemLoop:
|
||||
for it := range items {
|
||||
if it.typ == itemError {
|
||||
return nil, fmt.Errorf(it.val)
|
||||
}
|
||||
|
||||
switch it.typ {
|
||||
case itemIdentifier:
|
||||
currFieldName = it.val
|
||||
case itemString, itemBoolean, itemNumber:
|
||||
currTerm := simplejson.New()
|
||||
if strings.ContainsRune(it.val, '*') {
|
||||
currMatchType = matchTypeWildcard
|
||||
currPathAddition = "value"
|
||||
}
|
||||
path := []string{currMatchType, currFieldName}
|
||||
if len(currPathAddition) > 0 {
|
||||
path = append(path, currPathAddition)
|
||||
}
|
||||
currTerm.SetPath(path, it.val)
|
||||
terms = append(terms, currTerm)
|
||||
|
||||
// reset
|
||||
currFieldName = ""
|
||||
currMatchType = matchTypeMatch
|
||||
|
||||
case itemBooleanOp:
|
||||
thisBool := "must"
|
||||
if strings.ToLower(it.val) == "or" {
|
||||
thisBool = "should"
|
||||
}
|
||||
if len(currBool) == 0 {
|
||||
currBool = thisBool
|
||||
} else {
|
||||
if thisBool != currBool {
|
||||
// undefined behaviour order of precedence needs to be explicitly defined using parentheses
|
||||
return nil, fmt.Errorf("error parsing query. Cannot mix boolean operators without explicitly defining precedence with parentheses")
|
||||
}
|
||||
}
|
||||
case itemLeftParen:
|
||||
currTerm, err := parseQueryStringRec(items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
terms = append(terms, currTerm)
|
||||
case itemRightParen:
|
||||
break itemLoop
|
||||
case itemOperator:
|
||||
switch it.val {
|
||||
case "==":
|
||||
currMatchType = matchTypeMatch
|
||||
currPathAddition = ""
|
||||
case ">=":
|
||||
currMatchType = matchTypeRange
|
||||
currPathAddition = "gte"
|
||||
case "<=":
|
||||
currMatchType = matchTypeRange
|
||||
currPathAddition = "lte"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if len(currBool) == 0 {
|
||||
currBool = "must"
|
||||
}
|
||||
retTerm.SetPath([]string{"bool", currBool}, terms)
|
||||
return retTerm, nil
|
||||
}
|
||||
Reference in New Issue
Block a user