0
0
Fork 0

added support for boost with ^boostval in syntax query

closes #51
also found/fixed major bug in scoring, closes #61
This commit is contained in:
Marty Schoch 2014-08-06 19:36:23 -04:00
parent 41d4f67ee2
commit f69838d670
12 changed files with 655 additions and 427 deletions

View File

@ -13,9 +13,8 @@ import (
)
type SyntaxQuery struct {
Query string `json:"query"`
DefaultFieldVal string `json:"default_field,omitempty"`
BoostVal float64 `json:"boost,omitempty"`
Query string `json:"query"`
BoostVal float64 `json:"boost,omitempty"`
}
func NewSyntaxQuery(query string) *SyntaxQuery {
@ -34,21 +33,8 @@ func (q *SyntaxQuery) SetBoost(b float64) *SyntaxQuery {
return q
}
func (q *SyntaxQuery) DefaultField() string {
return q.DefaultFieldVal
}
func (q *SyntaxQuery) SetField(f string) *SyntaxQuery {
q.DefaultFieldVal = f
return q
}
func (q *SyntaxQuery) Searcher(i *indexImpl, explain bool) (search.Searcher, error) {
defaultField := q.DefaultFieldVal
if q.DefaultFieldVal == "" {
defaultField = i.m.defaultField()
}
newQuery, err := ParseQuerySyntax(q.Query, i.m, defaultField)
newQuery, err := ParseQuerySyntax(q.Query, i.m)
if err != nil {
return nil, err
}

View File

@ -23,60 +23,81 @@ a = make([]family, 1)
{
var acc [18]bool
var fun [18]func(rune) int
fun[11] = func(r rune) int {
fun[8] = func(r rune) int {
switch(r) {
case 92: return 11
case 98: return 12
case 114: return 13
case 34: return 5
case 110: return 5
case 117: return 6
case 47: return 7
case 116: return 8
case 110: return 9
case 102: return 10
case 92: return 8
case 34: return 9
case 114: return 10
case 116: return 11
case 102: return 12
case 98: return 13
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[6] = func(r rune) int {
fun[15] = func(r rune) int {
switch(r) {
case 114: return 2
case 34: return 4
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 14
case 92: return 3
case 98: return 14
case 110: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 16
case 98: return 16
default:
switch {
case 48 <= r && r <= 57: return 14
case 65 <= r && r <= 70: return 14
case 97 <= r && r <= 102: return 14
default: return 2
case 48 <= r && r <= 57: return 16
case 65 <= r && r <= 70: return 16
case 97 <= r && r <= 102: return 16
default: return 4
}
}
panic("unreachable")
}
acc[4] = true
fun[4] = func(r rune) int {
fun[10] = func(r rune) int {
switch(r) {
case 92: return -1
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
case 110: return 4
default:
switch {
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
acc[3] = true
fun[3] = func(r rune) int {
switch(r) {
case 116: return -1
case 102: return -1
case 98: return -1
case 114: return -1
case 34: return -1
case 110: return -1
case 117: return -1
case 47: return -1
case 116: return -1
case 110: return -1
case 102: return -1
case 92: return -1
case 34: return -1
case 114: return -1
default:
switch {
case 48 <= r && r <= 57: return -1
@ -87,60 +108,17 @@ fun[4] = func(r rune) int {
}
panic("unreachable")
}
fun[17] = func(r rune) int {
switch(r) {
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
}
}
panic("unreachable")
}
acc[5] = true
fun[5] = func(r rune) int {
switch(r) {
case 110: return 2
case 102: return 2
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 2
case 47: return 2
case 116: return 2
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
}
}
panic("unreachable")
}
fun[0] = func(r rune) int {
switch(r) {
case 114: return -1
case 34: return 1
case 116: return -1
case 102: return -1
case 98: return -1
case 110: return -1
case 117: return -1
case 47: return -1
case 116: return -1
case 110: return -1
case 102: return -1
case 92: return -1
case 98: return -1
case 34: return 1
default:
switch {
case 48 <= r && r <= 57: return -1
@ -151,254 +129,276 @@ fun[0] = func(r rune) int {
}
panic("unreachable")
}
fun[10] = func(r rune) int {
switch(r) {
case 114: return 2
case 34: return 4
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
case 92: return 3
case 98: return 2
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
}
}
panic("unreachable")
}
fun[16] = func(r rune) int {
switch(r) {
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 17
case 92: return 3
case 98: return 17
case 114: return 2
case 34: return 4
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 110: return 4
case 117: return 4
default:
switch {
case 48 <= r && r <= 57: return 17
case 65 <= r && r <= 70: return 17
case 97 <= r && r <= 102: return 17
default: return 2
default: return 4
}
}
panic("unreachable")
}
fun[13] = func(r rune) int {
fun[11] = func(r rune) int {
switch(r) {
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
case 110: return 4
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[7] = func(r rune) int {
fun[6] = func(r rune) int {
switch(r) {
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
case 110: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 14
case 98: return 14
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
}
}
panic("unreachable")
}
fun[2] = func(r rune) int {
switch(r) {
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 2
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
}
}
panic("unreachable")
}
fun[8] = func(r rune) int {
switch(r) {
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
}
}
panic("unreachable")
}
fun[3] = func(r rune) int {
switch(r) {
case 34: return 5
case 117: return 6
case 47: return 7
case 116: return 8
case 110: return 9
case 102: return 10
case 92: return 11
case 98: return 12
case 114: return 13
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
}
}
panic("unreachable")
}
fun[12] = func(r rune) int {
switch(r) {
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 2
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
}
}
panic("unreachable")
}
fun[14] = func(r rune) int {
switch(r) {
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 15
case 92: return 3
case 98: return 15
case 114: return 2
case 34: return 4
default:
switch {
case 48 <= r && r <= 57: return 15
case 65 <= r && r <= 70: return 15
case 97 <= r && r <= 102: return 15
default: return 2
}
}
panic("unreachable")
}
fun[15] = func(r rune) int {
switch(r) {
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 16
case 92: return 3
case 98: return 16
case 114: return 2
case 34: return 4
case 117: return 2
default:
switch {
case 48 <= r && r <= 57: return 16
case 65 <= r && r <= 70: return 16
case 97 <= r && r <= 102: return 16
default: return 2
case 48 <= r && r <= 57: return 14
case 65 <= r && r <= 70: return 14
case 97 <= r && r <= 102: return 14
default: return 4
}
}
panic("unreachable")
}
fun[1] = func(r rune) int {
switch(r) {
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 2
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
case 110: return 4
case 117: return 4
case 47: return 4
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[9] = func(r rune) int {
fun[7] = func(r rune) int {
switch(r) {
case 92: return 3
case 98: return 2
case 114: return 2
case 34: return 4
case 117: return 2
case 47: return 2
case 116: return 2
case 110: return 2
case 102: return 2
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
case 110: return 4
case 117: return 4
case 47: return 4
default:
switch {
case 48 <= r && r <= 57: return 2
case 65 <= r && r <= 70: return 2
case 97 <= r && r <= 102: return 2
default: return 2
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[13] = func(r rune) int {
switch(r) {
case 110: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
default:
switch {
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[5] = func(r rune) int {
switch(r) {
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
case 110: return 4
case 117: return 4
case 47: return 4
default:
switch {
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[17] = func(r rune) int {
switch(r) {
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
case 110: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
default:
switch {
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[12] = func(r rune) int {
switch(r) {
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
case 110: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
default:
switch {
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[14] = func(r rune) int {
switch(r) {
case 110: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 15
case 98: return 15
default:
switch {
case 48 <= r && r <= 57: return 15
case 65 <= r && r <= 70: return 15
case 97 <= r && r <= 102: return 15
default: return 4
}
}
panic("unreachable")
}
acc[9] = true
fun[9] = func(r rune) int {
switch(r) {
case 110: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
case 116: return 4
case 102: return 4
case 98: return 4
default:
switch {
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[4] = func(r rune) int {
switch(r) {
case 116: return 4
case 102: return 4
case 98: return 4
case 110: return 4
case 117: return 4
case 47: return 4
case 92: return 2
case 34: return 3
case 114: return 4
default:
switch {
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
}
fun[2] = func(r rune) int {
switch(r) {
case 110: return 5
case 117: return 6
case 47: return 7
case 92: return 8
case 34: return 9
case 114: return 10
case 116: return 11
case 102: return 12
case 98: return 13
default:
switch {
case 48 <= r && r <= 57: return 4
case 65 <= r && r <= 70: return 4
case 97 <= r && r <= 102: return 4
default: return 4
}
}
panic("unreachable")
@ -410,10 +410,9 @@ a0[0].id = 0
{
var acc [2]bool
var fun [2]func(rune) int
acc[1] = true
fun[1] = func(r rune) int {
fun[0] = func(r rune) int {
switch(r) {
case 43: return -1
case 43: return 1
default:
switch {
default: return -1
@ -421,9 +420,10 @@ fun[1] = func(r rune) int {
}
panic("unreachable")
}
fun[0] = func(r rune) int {
acc[1] = true
fun[1] = func(r rune) int {
switch(r) {
case 43: return 1
case 43: return -1
default:
switch {
default: return -1
@ -494,10 +494,9 @@ a0[3].id = 3
{
var acc [2]bool
var fun [2]func(rune) int
acc[1] = true
fun[1] = func(r rune) int {
fun[0] = func(r rune) int {
switch(r) {
case 94: return -1
case 94: return 1
default:
switch {
default: return -1
@ -505,9 +504,10 @@ fun[1] = func(r rune) int {
}
panic("unreachable")
}
fun[0] = func(r rune) int {
acc[1] = true
fun[1] = func(r rune) int {
switch(r) {
case 94: return 1
case 94: return -1
default:
switch {
default: return -1
@ -522,9 +522,10 @@ a0[4].id = 4
{
var acc [2]bool
var fun [2]func(rune) int
fun[0] = func(r rune) int {
acc[1] = true
fun[1] = func(r rune) int {
switch(r) {
case 40: return 1
case 40: return -1
default:
switch {
default: return -1
@ -532,10 +533,9 @@ fun[0] = func(r rune) int {
}
panic("unreachable")
}
acc[1] = true
fun[1] = func(r rune) int {
fun[0] = func(r rune) int {
switch(r) {
case 40: return -1
case 40: return 1
default:
switch {
default: return -1
@ -550,9 +550,10 @@ a0[5].id = 5
{
var acc [2]bool
var fun [2]func(rune) int
fun[0] = func(r rune) int {
acc[1] = true
fun[1] = func(r rune) int {
switch(r) {
case 41: return 1
case 41: return -1
default:
switch {
default: return -1
@ -560,10 +561,9 @@ fun[0] = func(r rune) int {
}
panic("unreachable")
}
acc[1] = true
fun[1] = func(r rune) int {
fun[0] = func(r rune) int {
switch(r) {
case 41: return -1
case 41: return 1
default:
switch {
default: return -1
@ -578,21 +578,8 @@ a0[6].id = 6
{
var acc [5]bool
var fun [5]func(rune) int
acc[2] = true
fun[2] = func(r rune) int {
switch(r) {
case 45: return -1
default:
switch {
case 48 <= r && r <= 48: return -1
case 49 <= r && r <= 57: return -1
default: return -1
}
}
panic("unreachable")
}
acc[3] = true
fun[3] = func(r rune) int {
acc[4] = true
fun[4] = func(r rune) int {
switch(r) {
case 45: return -1
default:
@ -604,8 +591,20 @@ fun[3] = func(r rune) int {
}
panic("unreachable")
}
acc[4] = true
fun[4] = func(r rune) int {
fun[0] = func(r rune) int {
switch(r) {
case 45: return 1
default:
switch {
case 48 <= r && r <= 48: return 2
case 49 <= r && r <= 57: return 3
default: return -1
}
}
panic("unreachable")
}
acc[3] = true
fun[3] = func(r rune) int {
switch(r) {
case 45: return -1
default:
@ -629,13 +628,14 @@ fun[1] = func(r rune) int {
}
panic("unreachable")
}
fun[0] = func(r rune) int {
acc[2] = true
fun[2] = func(r rune) int {
switch(r) {
case 45: return 1
case 45: return -1
default:
switch {
case 48 <= r && r <= 48: return 2
case 49 <= r && r <= 57: return 3
case 48 <= r && r <= 48: return -1
case 49 <= r && r <= 57: return -1
default: return -1
}
}
@ -648,12 +648,11 @@ a0[7].id = 7
{
var acc [2]bool
var fun [2]func(rune) int
acc[1] = true
fun[1] = func(r rune) int {
fun[0] = func(r rune) int {
switch(r) {
case 32: return 1
case 10: return 1
case 9: return 1
case 10: return 1
case 32: return 1
default:
switch {
default: return -1
@ -661,11 +660,12 @@ fun[1] = func(r rune) int {
}
panic("unreachable")
}
fun[0] = func(r rune) int {
acc[1] = true
fun[1] = func(r rune) int {
switch(r) {
case 9: return 1
case 32: return 1
case 10: return 1
case 32: return 1
default:
switch {
default: return -1
@ -680,17 +680,18 @@ a0[8].id = 8
{
var acc [2]bool
var fun [2]func(rune) int
fun[0] = func(r rune) int {
acc[1] = true
fun[1] = func(r rune) int {
switch(r) {
case 45: return -1
case 32: return -1
case 13: return -1
case 94: return -1
case 58: return -1
case 9: return -1
case 12: return -1
case 10: return -1
case 94: return -1
case 32: return -1
case 43: return -1
case 9: return -1
case 45: return -1
case 12: return -1
case 13: return -1
default:
switch {
default: return 1
@ -698,18 +699,17 @@ fun[0] = func(r rune) int {
}
panic("unreachable")
}
acc[1] = true
fun[1] = func(r rune) int {
fun[0] = func(r rune) int {
switch(r) {
case 94: return -1
case 58: return -1
case 9: return -1
case 12: return -1
case 10: return -1
case 43: return -1
case 45: return -1
case 32: return -1
case 12: return -1
case 13: return -1
case 58: return -1
case 10: return -1
case 94: return -1
case 32: return -1
case 43: return -1
default:
switch {
default: return 1

View File

@ -62,7 +62,7 @@ searchBase:
STRING {
str := $1.s
logDebugGrammar("STRING - %s", str)
q := NewMatchQuery(str).SetField(parsingDefaultField)
q := NewMatchQuery(str)
if parsingMust {
parsingMustList.AddQuery(q)
parsingMust = false
@ -72,12 +72,13 @@ STRING {
} else {
parsingShouldList.AddQuery(q)
}
parsingLastQuery = q
}
|
PHRASE {
phrase := $1.s
logDebugGrammar("PHRASE - %s", phrase)
q := NewMatchPhraseQuery(phrase).SetField(parsingDefaultField)
q := NewMatchPhraseQuery(phrase)
if parsingMust {
parsingMustList.AddQuery(q)
parsingMust = false
@ -87,6 +88,7 @@ PHRASE {
} else {
parsingShouldList.AddQuery(q)
}
parsingLastQuery = q
}
|
STRING COLON STRING {
@ -103,6 +105,7 @@ STRING COLON STRING {
} else {
parsingShouldList.AddQuery(q)
}
parsingLastQuery = q
}
|
STRING COLON PHRASE {
@ -119,14 +122,23 @@ STRING COLON PHRASE {
} else {
parsingShouldList.AddQuery(q)
}
parsingLastQuery = q
};
searchBoost:
BOOST INT {
boost := $1.n
boost := $2.n
if parsingLastQuery != nil {
switch parsingLastQuery := parsingLastQuery.(type) {
case *MatchQuery:
parsingLastQuery.SetBoost(float64(boost))
case *MatchPhraseQuery:
parsingLastQuery.SetBoost(float64(boost))
}
}
logDebugGrammar("BOOST %d", boost)
}
};
searchSuffix:
/* empty */ {

View File

@ -16,23 +16,22 @@ import (
var crashHard = false
var parserMutex sync.Mutex
var parsingDefaultField string
var parsingMust bool
var parsingMustNot bool
var debugParser bool
var debugLexer bool
var parsingLastQuery Query
var parsingMustList *ConjunctionQuery
var parsingMustNotList *DisjunctionQuery
var parsingShouldList *DisjunctionQuery
var parsingIndexMapping *IndexMapping
func ParseQuerySyntax(query string, mapping *IndexMapping, defaultField string) (rq Query, err error) {
func ParseQuerySyntax(query string, mapping *IndexMapping) (rq Query, err error) {
parserMutex.Lock()
defer parserMutex.Unlock()
parsingIndexMapping = mapping
parsingDefaultField = defaultField
parsingMustList = NewConjunctionQuery([]Query{})
parsingMustNotList = NewDisjunctionQuery([]Query{})
parsingShouldList = NewDisjunctionQuery([]Query{})

179
query_syntax_parser_test.go Normal file
View File

@ -0,0 +1,179 @@
// Copyright (c) 2014 Couchbase, Inc.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
package bleve
import (
"reflect"
"testing"
)
func TestQuerySyntaxParserValid(t *testing.T) {
tests := []struct {
input string
result Query
mapping *IndexMapping
}{
{
input: "test",
mapping: NewIndexMapping(),
result: NewBooleanQuery(
nil,
NewDisjunctionQuery(
[]Query{
NewMatchQuery("test"),
}),
nil),
},
{
input: `"test phrase 1"`,
mapping: NewIndexMapping(),
result: NewBooleanQuery(
nil,
NewDisjunctionQuery(
[]Query{
NewMatchPhraseQuery("test phrase 1"),
}),
nil),
},
{
input: "field:test",
mapping: NewIndexMapping(),
result: NewBooleanQuery(
nil,
NewDisjunctionQuery(
[]Query{
NewMatchQuery("test").SetField("field"),
}),
nil),
},
{
input: "+field1:test1",
mapping: NewIndexMapping(),
result: NewBooleanQuery(
NewConjunctionQuery(
[]Query{
NewMatchQuery("test1").SetField("field1"),
}),
nil,
nil),
},
{
input: "-field2:test2",
mapping: NewIndexMapping(),
result: NewBooleanQuery(
nil,
nil,
NewDisjunctionQuery(
[]Query{
NewMatchQuery("test2").SetField("field2"),
})),
},
{
input: `field3:"test phrase 2"`,
mapping: NewIndexMapping(),
result: NewBooleanQuery(
nil,
NewDisjunctionQuery(
[]Query{
NewMatchPhraseQuery("test phrase 2").SetField("field3"),
}),
nil),
},
{
input: `+field4:"test phrase 1"`,
mapping: NewIndexMapping(),
result: NewBooleanQuery(
NewConjunctionQuery(
[]Query{
NewMatchPhraseQuery("test phrase 1").SetField("field4"),
}),
nil,
nil),
},
{
input: `-field5:"test phrase 2"`,
mapping: NewIndexMapping(),
result: NewBooleanQuery(
nil,
nil,
NewDisjunctionQuery(
[]Query{
NewMatchPhraseQuery("test phrase 2").SetField("field5"),
})),
},
{
input: `+field6:test3 -field7:test4 field8:test5`,
mapping: NewIndexMapping(),
result: NewBooleanQuery(
NewConjunctionQuery(
[]Query{
NewMatchQuery("test3").SetField("field6"),
}),
NewDisjunctionQuery(
[]Query{
NewMatchQuery("test5").SetField("field8"),
}),
NewDisjunctionQuery(
[]Query{
NewMatchQuery("test4").SetField("field7"),
})),
},
{
input: "test^3",
mapping: NewIndexMapping(),
result: NewBooleanQuery(
nil,
NewDisjunctionQuery(
[]Query{
NewMatchQuery("test").SetBoost(3.0),
}),
nil),
},
{
input: "test^3 other^6",
mapping: NewIndexMapping(),
result: NewBooleanQuery(
nil,
NewDisjunctionQuery(
[]Query{
NewMatchQuery("test").SetBoost(3.0),
NewMatchQuery("other").SetBoost(6.0),
}),
nil),
},
}
for _, test := range tests {
q, err := ParseQuerySyntax(test.input, test.mapping)
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(q, test.result) {
t.Errorf("Expected %#v, got %#v: for %s", test.result, q, test.input)
}
}
}
func TestQuerySyntaxParserInvalid(t *testing.T) {
tests := []struct {
input string
}{
{"^"},
{"^5"},
}
for _, test := range tests {
_, err := ParseQuerySyntax(test.input, NewIndexMapping())
if err == nil {
t.Errorf("expected error, got nil for `%s`", test.input)
}
}
}

View File

@ -15,6 +15,7 @@ import (
)
type TermBooleanSearcher struct {
initialized bool
index index.Index
mustSearcher *TermConjunctionSearcher
shouldSearcher *TermDisjunctionSearcher
@ -38,11 +39,6 @@ func NewTermBooleanSearcher(index index.Index, mustSearcher *TermConjunctionSear
scorer: NewTermConjunctionQueryScorer(explain),
}
rv.computeQueryNorm()
err := rv.initSearchers()
if err != nil {
return nil, err
}
return &rv, nil
}
@ -99,6 +95,7 @@ func (s *TermBooleanSearcher) initSearchers() error {
s.currentId = ""
}
s.initialized = true
return nil
}
@ -150,6 +147,13 @@ func (s *TermBooleanSearcher) SetQueryNorm(qnorm float64) {
func (s *TermBooleanSearcher) Next() (*DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers()
if err != nil {
return nil, err
}
}
var err error
var rv *DocumentMatch
@ -172,7 +176,7 @@ func (s *TermBooleanSearcher) Next() (*DocumentMatch, error) {
}
if s.currShould != nil && s.currShould.ID < s.currentId {
// advance shoudl searcher to our candidate entry
// advance should searcher to our candidate entry
s.currShould, err = s.shouldSearcher.Advance(s.currentId)
if err != nil {
return nil, err
@ -216,6 +220,14 @@ func (s *TermBooleanSearcher) Next() (*DocumentMatch, error) {
}
func (s *TermBooleanSearcher) Advance(ID string) (*DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers()
if err != nil {
return nil, err
}
}
var err error
if s.mustSearcher != nil {
s.currMust, err = s.mustSearcher.Advance(ID)
@ -248,6 +260,7 @@ func (s *TermBooleanSearcher) Advance(ID string) (*DocumentMatch, error) {
}
func (s *TermBooleanSearcher) Count() uint64 {
// for now return a worst case
var sum uint64 = 0
if s.mustSearcher != nil {

View File

@ -232,7 +232,7 @@ func TestTermBooleanSearch(t *testing.T) {
results: []*DocumentMatch{
&DocumentMatch{
ID: "1",
Score: 1.6775110856165738,
Score: 0.9818005051949021,
},
&DocumentMatch{
ID: "3",
@ -302,7 +302,7 @@ func TestTermBooleanSearch(t *testing.T) {
results: []*DocumentMatch{
&DocumentMatch{
ID: "1",
Score: 2.905938399789078,
Score: 2.0097428702814377,
},
},
},

View File

@ -15,6 +15,7 @@ import (
)
type PhraseSearcher struct {
initialized bool
index index.Index
mustSearcher *TermConjunctionSearcher
queryNorm float64
@ -32,11 +33,6 @@ func NewPhraseSearcher(index index.Index, mustSearcher *TermConjunctionSearcher,
terms: terms,
}
rv.computeQueryNorm()
err := rv.initSearchers()
if err != nil {
return nil, err
}
return &rv, nil
}
@ -65,6 +61,7 @@ func (s *PhraseSearcher) initSearchers() error {
}
}
s.initialized = true
return nil
}
@ -93,6 +90,13 @@ func (s *PhraseSearcher) SetQueryNorm(qnorm float64) {
}
func (s *PhraseSearcher) Next() (*DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers()
if err != nil {
return nil, err
}
}
var rv *DocumentMatch
for s.currMust != nil {
rvftlm := make(FieldTermLocationMap, 0)
@ -150,6 +154,12 @@ func (s *PhraseSearcher) Next() (*DocumentMatch, error) {
}
func (s *PhraseSearcher) Advance(ID string) (*DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers()
if err != nil {
return nil, err
}
}
s.mustSearcher.Advance(ID)
return s.Next()
}

View File

@ -16,13 +16,14 @@ import (
)
type TermConjunctionSearcher struct {
index index.Index
searchers OrderedSearcherList
explain bool
queryNorm float64
currs []*DocumentMatch
currentId string
scorer *TermConjunctionQueryScorer
initialized bool
index index.Index
searchers OrderedSearcherList
explain bool
queryNorm float64
currs []*DocumentMatch
currentId string
scorer *TermConjunctionQueryScorer
}
func NewTermConjunctionSearcher(index index.Index, qsearchers []Searcher, explain bool) (*TermConjunctionSearcher, error) {
@ -42,11 +43,6 @@ func NewTermConjunctionSearcher(index index.Index, qsearchers []Searcher, explai
scorer: NewTermConjunctionQueryScorer(explain),
}
rv.computeQueryNorm()
err := rv.initSearchers()
if err != nil {
return nil, err
}
return &rv, nil
}
@ -82,6 +78,7 @@ func (s *TermConjunctionSearcher) initSearchers() error {
}
}
s.initialized = true
return nil
}
@ -100,6 +97,12 @@ func (s *TermConjunctionSearcher) SetQueryNorm(qnorm float64) {
}
func (s *TermConjunctionSearcher) Next() (*DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers()
if err != nil {
return nil, err
}
}
var rv *DocumentMatch
var err error
OUTER:
@ -146,6 +149,12 @@ OUTER:
}
func (s *TermConjunctionSearcher) Advance(ID string) (*DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers()
if err != nil {
return nil, err
}
}
var err error
for i, searcher := range s.searchers {
s.currs[i], err = searcher.Advance(ID)

View File

@ -16,13 +16,14 @@ import (
)
type TermDisjunctionSearcher struct {
index index.Index
searchers OrderedSearcherList
queryNorm float64
currs []*DocumentMatch
currentId string
scorer *TermDisjunctionQueryScorer
min float64
initialized bool
index index.Index
searchers OrderedSearcherList
queryNorm float64
currs []*DocumentMatch
currentId string
scorer *TermDisjunctionQueryScorer
min float64
}
func NewTermDisjunctionSearcher(index index.Index, qsearchers []Searcher, min float64, explain bool) (*TermDisjunctionSearcher, error) {
@ -42,11 +43,6 @@ func NewTermDisjunctionSearcher(index index.Index, qsearchers []Searcher, min fl
min: min,
}
rv.computeQueryNorm()
err := rv.initSearchers()
if err != nil {
return nil, err
}
return &rv, nil
}
@ -75,6 +71,7 @@ func (s *TermDisjunctionSearcher) initSearchers() error {
}
s.currentId = s.nextSmallestId()
s.initialized = true
return nil
}
@ -103,6 +100,12 @@ func (s *TermDisjunctionSearcher) SetQueryNorm(qnorm float64) {
}
func (s *TermDisjunctionSearcher) Next() (*DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers()
if err != nil {
return nil, err
}
}
var err error
var rv *DocumentMatch
matching := make([]*DocumentMatch, 0)
@ -139,7 +142,12 @@ func (s *TermDisjunctionSearcher) Next() (*DocumentMatch, error) {
}
func (s *TermDisjunctionSearcher) Advance(ID string) (*DocumentMatch, error) {
if !s.initialized {
err := s.initSearchers()
if err != nil {
return nil, err
}
}
// get all searchers pointing at their first match
var err error
for i, termSearcher := range s.searchers {

View File

@ -72,11 +72,11 @@ func TestTermDisjunctionSearch(t *testing.T) {
results: []*DocumentMatch{
&DocumentMatch{
ID: "1",
Score: 0.33875554280828685,
Score: 0.2765927424732821,
},
&DocumentMatch{
ID: "3",
Score: 0.33875554280828685,
Score: 0.2765927424732821,
},
&DocumentMatch{
ID: "4",

30
y.go
View File

@ -383,7 +383,7 @@ yydefault:
{
str := yyS[yypt-0].s
logDebugGrammar("STRING - %s", str)
q := NewMatchQuery(str).SetField(parsingDefaultField)
q := NewMatchQuery(str)
if parsingMust {
parsingMustList.AddQuery(q)
parsingMust = false
@ -393,13 +393,14 @@ yydefault:
} else {
parsingShouldList.AddQuery(q)
}
parsingLastQuery = q
}
case 10:
//line query_syntax.y:77
//line query_syntax.y:78
{
phrase := yyS[yypt-0].s
logDebugGrammar("PHRASE - %s", phrase)
q := NewMatchPhraseQuery(phrase).SetField(parsingDefaultField)
q := NewMatchPhraseQuery(phrase)
if parsingMust {
parsingMustList.AddQuery(q)
parsingMust = false
@ -409,9 +410,10 @@ yydefault:
} else {
parsingShouldList.AddQuery(q)
}
parsingLastQuery = q
}
case 11:
//line query_syntax.y:92
//line query_syntax.y:94
{
field := yyS[yypt-2].s
str := yyS[yypt-0].s
@ -426,9 +428,10 @@ yydefault:
} else {
parsingShouldList.AddQuery(q)
}
parsingLastQuery = q
}
case 12:
//line query_syntax.y:108
//line query_syntax.y:111
{
field := yyS[yypt-2].s
phrase := yyS[yypt-0].s
@ -443,20 +446,29 @@ yydefault:
} else {
parsingShouldList.AddQuery(q)
}
parsingLastQuery = q
}
case 13:
//line query_syntax.y:126
//line query_syntax.y:130
{
boost := yyS[yypt-1].n
boost := yyS[yypt-0].n
if parsingLastQuery != nil {
switch parsingLastQuery := parsingLastQuery.(type) {
case *MatchQuery:
parsingLastQuery.SetBoost(float64(boost))
case *MatchPhraseQuery:
parsingLastQuery.SetBoost(float64(boost))
}
}
logDebugGrammar("BOOST %d", boost)
}
case 14:
//line query_syntax.y:132
//line query_syntax.y:144
{
}
case 15:
//line query_syntax.y:136
//line query_syntax.y:148
{
}