2014-08-07 01:36:23 +02:00
|
|
|
// Copyright (c) 2014 Couchbase, Inc.
|
2016-10-02 16:13:14 +02:00
|
|
|
//
|
|
|
|
// 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.
|
2014-08-29 20:18:36 +02:00
|
|
|
|
2016-09-20 03:12:36 +02:00
|
|
|
package query
|
2014-08-07 01:36:23 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
2016-09-01 03:23:03 +02:00
|
|
|
"strings"
|
2014-08-07 01:36:23 +02:00
|
|
|
"testing"
|
2016-09-23 03:24:43 +02:00
|
|
|
"time"
|
2016-09-18 15:33:18 +02:00
|
|
|
|
|
|
|
"github.com/blevesearch/bleve/mapping"
|
2014-08-07 01:36:23 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestQuerySyntaxParserValid(t *testing.T) {
|
2015-05-21 21:43:13 +02:00
|
|
|
fivePointOh := 5.0
|
|
|
|
theTruth := true
|
|
|
|
theFalsehood := false
|
2016-09-23 03:24:43 +02:00
|
|
|
theDate, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2014-08-07 01:36:23 +02:00
|
|
|
tests := []struct {
|
|
|
|
input string
|
|
|
|
result Query
|
2016-09-18 15:33:18 +02:00
|
|
|
mapping mapping.IndexMapping
|
2014-08-07 01:36:23 +02:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
input: "test",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
|
|
|
NewMatchQuery("test"),
|
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `"test phrase 1"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
|
|
|
NewMatchPhraseQuery("test phrase 1"),
|
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: "field:test",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("test")
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
nil),
|
|
|
|
},
|
2015-05-21 21:43:13 +02:00
|
|
|
// - is allowed inside a term, just not the start
|
|
|
|
{
|
|
|
|
input: "field:t-est",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("t-est")
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// + is allowed inside a term, just not the start
|
|
|
|
{
|
|
|
|
input: "field:t+est",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("t+est")
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// > is allowed inside a term, just not the start
|
|
|
|
{
|
|
|
|
input: "field:t>est",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("t>est")
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// < is allowed inside a term, just not the start
|
|
|
|
{
|
|
|
|
input: "field:t<est",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("t<est")
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// = is allowed inside a term, just not the start
|
|
|
|
{
|
|
|
|
input: "field:t=est",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("t=est")
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
{
|
|
|
|
input: "+field1:test1",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("test1")
|
|
|
|
q.SetField("field1")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
nil,
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: "-field2:test2",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
nil,
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("test2")
|
|
|
|
q.SetField("field2")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
}),
|
2014-08-07 01:36:23 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `field3:"test phrase 2"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchPhraseQuery("test phrase 2")
|
|
|
|
q.SetField("field3")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `+field4:"test phrase 1"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchPhraseQuery("test phrase 1")
|
|
|
|
q.SetField("field4")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
nil,
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `-field5:"test phrase 2"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
nil,
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchPhraseQuery("test phrase 2")
|
|
|
|
q.SetField("field5")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
}),
|
2014-08-07 01:36:23 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `+field6:test3 -field7:test4 field8:test5`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("test3")
|
|
|
|
q.SetField("field6")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
},
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("test5")
|
|
|
|
q.SetField("field8")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
},
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("test4")
|
|
|
|
q.SetField("field7")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
}),
|
2014-08-07 01:36:23 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
input: "test^3",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("test")
|
|
|
|
q.SetBoost(3.0)
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: "test^3 other^6",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-08-07 01:36:23 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
2014-08-29 22:27:32 +02:00
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("test")
|
|
|
|
q.SetBoost(3.0)
|
|
|
|
return q
|
|
|
|
}(),
|
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("other")
|
|
|
|
q.SetBoost(6.0)
|
|
|
|
return q
|
|
|
|
}(),
|
2014-08-29 22:27:32 +02:00
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
nil),
|
|
|
|
},
|
2014-10-11 05:36:31 +02:00
|
|
|
{
|
|
|
|
input: "33",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-10-11 05:36:31 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery("33"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: "field:33",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-10-11 05:36:31 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("33")
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2014-10-11 05:36:31 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2014-10-11 05:45:57 +02:00
|
|
|
{
|
|
|
|
input: "cat-dog",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-10-11 05:45:57 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery("cat-dog"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2014-10-24 19:39:48 +02:00
|
|
|
{
|
|
|
|
input: "watex~",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-10-24 19:39:48 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("watex")
|
|
|
|
q.SetFuzziness(1)
|
|
|
|
return q
|
|
|
|
}(),
|
2014-10-24 19:39:48 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: "watex~2",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-10-24 19:39:48 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("watex")
|
|
|
|
q.SetFuzziness(2)
|
|
|
|
return q
|
|
|
|
}(),
|
2014-10-24 19:39:48 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: "watex~ 2",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2014-10-24 19:39:48 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("watex")
|
|
|
|
q.SetFuzziness(1)
|
|
|
|
return q
|
|
|
|
}(),
|
2014-10-24 19:39:48 +02:00
|
|
|
NewMatchQuery("2"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2015-01-19 22:20:32 +01:00
|
|
|
{
|
|
|
|
input: "field:watex~",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-01-19 22:20:32 +01:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("watex")
|
|
|
|
q.SetFuzziness(1)
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-01-19 22:20:32 +01:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: "field:watex~2",
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-01-19 22:20:32 +01:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("watex")
|
|
|
|
q.SetFuzziness(2)
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-01-19 22:20:32 +01:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2015-05-21 21:43:13 +02:00
|
|
|
{
|
|
|
|
input: `field:555c3bb06f7a127cda000005`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("555c3bb06f7a127cda000005")
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `field:>5`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewNumericRangeInclusiveQuery(&fivePointOh, nil, &theFalsehood, nil)
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `field:>=5`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewNumericRangeInclusiveQuery(&fivePointOh, nil, &theTruth, nil)
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `field:<5`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewNumericRangeInclusiveQuery(nil, &fivePointOh, nil, &theFalsehood)
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `field:<=5`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2015-05-21 21:43:13 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewNumericRangeInclusiveQuery(nil, &fivePointOh, nil, &theTruth)
|
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2015-05-21 21:43:13 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2016-04-22 23:12:10 +02:00
|
|
|
{
|
2016-09-23 03:24:43 +02:00
|
|
|
input: `field:>"2006-01-02T15:04:05Z"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-04-22 23:12:10 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
2016-09-23 03:24:43 +02:00
|
|
|
q := NewDateRangeInclusiveQuery(theDate, time.Time{}, &theFalsehood, nil)
|
2016-09-23 01:49:31 +02:00
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2016-04-22 23:12:10 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
2016-09-23 03:24:43 +02:00
|
|
|
input: `field:>="2006-01-02T15:04:05Z"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-04-22 23:12:10 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
2016-09-23 03:24:43 +02:00
|
|
|
q := NewDateRangeInclusiveQuery(theDate, time.Time{}, &theTruth, nil)
|
2016-09-23 01:49:31 +02:00
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2016-04-22 23:12:10 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
2016-09-23 03:24:43 +02:00
|
|
|
input: `field:<"2006-01-02T15:04:05Z"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-04-22 23:12:10 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
2016-09-23 03:24:43 +02:00
|
|
|
q := NewDateRangeInclusiveQuery(time.Time{}, theDate, nil, &theFalsehood)
|
2016-09-23 01:49:31 +02:00
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2016-04-22 23:12:10 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
2016-09-23 03:24:43 +02:00
|
|
|
input: `field:<="2006-01-02T15:04:05Z"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-04-22 23:12:10 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
2016-09-23 03:24:43 +02:00
|
|
|
q := NewDateRangeInclusiveQuery(time.Time{}, theDate, nil, &theTruth)
|
2016-09-23 01:49:31 +02:00
|
|
|
q.SetField("field")
|
|
|
|
return q
|
|
|
|
}(),
|
2016-04-22 23:12:10 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2016-09-01 03:23:03 +02:00
|
|
|
{
|
|
|
|
input: `/mar.*ty/`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 03:23:03 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewRegexpQuery("mar.*ty"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `name:/mar.*ty/`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 03:23:03 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewRegexpQuery("mar.*ty")
|
|
|
|
q.SetField("name")
|
|
|
|
return q
|
|
|
|
}(),
|
2016-09-01 03:23:03 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `mart*`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 03:23:03 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewWildcardQuery("mart*"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `name:mart*`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 03:23:03 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewWildcardQuery("mart*")
|
|
|
|
q.SetField("name")
|
|
|
|
return q
|
|
|
|
}(),
|
2016-09-01 03:23:03 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2016-09-01 19:16:07 +02:00
|
|
|
|
|
|
|
// tests for escaping
|
|
|
|
|
|
|
|
// escape : as field delimeter
|
|
|
|
{
|
|
|
|
input: `name\:marty`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery("name:marty"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// first colon delimiter, second escaped
|
|
|
|
{
|
|
|
|
input: `name:marty\:couchbase`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery("marty:couchbase")
|
|
|
|
q.SetField("name")
|
|
|
|
return q
|
|
|
|
}(),
|
2016-09-01 19:16:07 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// escape space, single arguemnt to match query
|
|
|
|
{
|
|
|
|
input: `marty\ couchbase`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery("marty couchbase"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// escape leading plus, not a must clause
|
|
|
|
{
|
|
|
|
input: `\+marty`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery("+marty"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// escape leading minus, not a must not clause
|
|
|
|
{
|
|
|
|
input: `\-marty`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery("-marty"),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// escape quote inside of phrase
|
|
|
|
{
|
|
|
|
input: `"what does \"quote\" mean"`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchPhraseQuery(`what does "quote" mean`),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// escaping an unsupported character retains backslash
|
|
|
|
{
|
|
|
|
input: `can\ i\ escap\e`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery(`can i escap\e`),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// leading spaces
|
|
|
|
{
|
|
|
|
input: ` what`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery(`what`),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// no boost value defaults to 1
|
|
|
|
{
|
|
|
|
input: `term^`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
2016-09-23 01:49:31 +02:00
|
|
|
func() Query {
|
|
|
|
q := NewMatchQuery(`term`)
|
|
|
|
q.SetBoost(1.0)
|
|
|
|
return q
|
|
|
|
}(),
|
2016-09-01 19:16:07 +02:00
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
// weird lexer cases, something that starts like a number
|
|
|
|
// but contains escape and ends up as string
|
|
|
|
{
|
|
|
|
input: `3.0\:`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery(`3.0:`),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `3.0\a`,
|
2016-09-20 03:12:36 +02:00
|
|
|
mapping: mapping.NewIndexMapping(),
|
2016-09-01 19:16:07 +02:00
|
|
|
result: NewBooleanQuery(
|
|
|
|
nil,
|
|
|
|
[]Query{
|
|
|
|
NewMatchQuery(`3.0\a`),
|
|
|
|
},
|
|
|
|
nil),
|
|
|
|
},
|
2014-08-07 01:36:23 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 21:43:13 +02:00
|
|
|
// turn on lexer debugging
|
|
|
|
// debugLexer = true
|
2016-09-01 19:16:07 +02:00
|
|
|
// debugParser = true
|
|
|
|
// logger = log.New(os.Stderr, "bleve ", log.LstdFlags)
|
2015-05-21 21:43:13 +02:00
|
|
|
|
2014-08-07 01:36:23 +02:00
|
|
|
for _, test := range tests {
|
|
|
|
|
2016-04-22 23:12:10 +02:00
|
|
|
q, err := parseQuerySyntax(test.input)
|
2014-08-07 01:36:23 +02:00
|
|
|
if err != nil {
|
2016-09-01 19:16:07 +02:00
|
|
|
t.Fatal(err)
|
2014-08-07 01:36:23 +02:00
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(q, test.result) {
|
|
|
|
t.Errorf("Expected %#v, got %#v: for %s", test.result, q, test.input)
|
2016-09-20 03:12:36 +02:00
|
|
|
t.Errorf("Expected %#v, got %#v: for %s", test.result.(*BooleanQuery).Should.(*DisjunctionQuery).Disjuncts[0], q.(*BooleanQuery).Should.(*DisjunctionQuery).Disjuncts[0], test.input)
|
2014-08-07 01:36:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestQuerySyntaxParserInvalid(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
input string
|
|
|
|
}{
|
|
|
|
{"^"},
|
|
|
|
{"^5"},
|
2015-05-21 21:43:13 +02:00
|
|
|
{"field:-text"},
|
|
|
|
{"field:+text"},
|
|
|
|
{"field:>text"},
|
|
|
|
{"field:>=text"},
|
|
|
|
{"field:<text"},
|
|
|
|
{"field:<=text"},
|
|
|
|
{"field:~text"},
|
|
|
|
{"field:^text"},
|
|
|
|
{"field::text"},
|
2016-09-01 19:16:07 +02:00
|
|
|
{`"this is the time`},
|
|
|
|
{`cat^3\:`},
|
|
|
|
{`cat^3\0`},
|
|
|
|
{`cat~3\:`},
|
|
|
|
{`cat~3\0`},
|
2014-08-07 01:36:23 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 21:43:13 +02:00
|
|
|
// turn on lexer debugging
|
|
|
|
// debugLexer = true
|
|
|
|
// logger = log.New(os.Stderr, "bleve", log.LstdFlags)
|
|
|
|
|
2014-08-07 01:36:23 +02:00
|
|
|
for _, test := range tests {
|
2016-04-22 23:12:10 +02:00
|
|
|
_, err := parseQuerySyntax(test.input)
|
2014-08-07 01:36:23 +02:00
|
|
|
if err == nil {
|
|
|
|
t.Errorf("expected error, got nil for `%s`", test.input)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-09-01 03:23:03 +02:00
|
|
|
|
|
|
|
func BenchmarkLexer(b *testing.B) {
|
|
|
|
|
|
|
|
for n := 0; n < b.N; n++ {
|
|
|
|
var tokenTypes []int
|
|
|
|
var tokens []yySymType
|
|
|
|
r := strings.NewReader(`+field4:"test phrase 1"`)
|
2016-09-01 19:16:07 +02:00
|
|
|
l := newQueryStringLex(r)
|
2016-09-01 03:23:03 +02:00
|
|
|
var lval yySymType
|
|
|
|
rv := l.Lex(&lval)
|
|
|
|
for rv > 0 {
|
|
|
|
tokenTypes = append(tokenTypes, rv)
|
|
|
|
tokens = append(tokens, lval)
|
|
|
|
lval.s = ""
|
|
|
|
lval.n = 0
|
|
|
|
rv = l.Lex(&lval)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|