parent
082a5b0b03
commit
41914181ae
|
@ -10,6 +10,7 @@ package document
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/couchbaselabs/bleve/analysis"
|
||||
|
@ -17,9 +18,11 @@ import (
|
|||
)
|
||||
|
||||
const DEFAULT_DATETIME_INDEXING_OPTIONS = STORE_FIELD | INDEX_FIELD
|
||||
|
||||
const DEFAULT_DATETIME_PRECISION_STEP uint = 4
|
||||
|
||||
var MinTimeRepresentable = time.Unix(0, math.MinInt64)
|
||||
var MaxTimeRepresentable = time.Unix(0, math.MaxInt64)
|
||||
|
||||
type DateTimeField struct {
|
||||
name string
|
||||
arrayPositions []uint64
|
||||
|
@ -100,17 +103,27 @@ func NewDateTimeFieldFromBytes(name string, arrayPositions []uint64, value []byt
|
|||
}
|
||||
}
|
||||
|
||||
func NewDateTimeField(name string, arrayPositions []uint64, dt time.Time) *DateTimeField {
|
||||
func NewDateTimeField(name string, arrayPositions []uint64, dt time.Time) (*DateTimeField, error) {
|
||||
return NewDateTimeFieldWithIndexingOptions(name, arrayPositions, dt, DEFAULT_DATETIME_INDEXING_OPTIONS)
|
||||
}
|
||||
|
||||
func NewDateTimeFieldWithIndexingOptions(name string, arrayPositions []uint64, dt time.Time, options IndexingOptions) *DateTimeField {
|
||||
dtInt64 := dt.UnixNano()
|
||||
prefixCoded := numeric_util.MustNewPrefixCodedInt64(dtInt64, 0)
|
||||
return &DateTimeField{
|
||||
name: name,
|
||||
arrayPositions: arrayPositions,
|
||||
value: prefixCoded,
|
||||
options: options,
|
||||
func NewDateTimeFieldWithIndexingOptions(name string, arrayPositions []uint64, dt time.Time, options IndexingOptions) (*DateTimeField, error) {
|
||||
if canRepresent(dt) {
|
||||
dtInt64 := dt.UnixNano()
|
||||
prefixCoded := numeric_util.MustNewPrefixCodedInt64(dtInt64, 0)
|
||||
return &DateTimeField{
|
||||
name: name,
|
||||
arrayPositions: arrayPositions,
|
||||
value: prefixCoded,
|
||||
options: options,
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("cannot represent %s in this type", dt)
|
||||
}
|
||||
|
||||
func canRepresent(dt time.Time) bool {
|
||||
if dt.Before(MinTimeRepresentable) || dt.After(MaxTimeRepresentable) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -54,9 +54,9 @@ var people = []*Person{
|
|||
Identifier: "a",
|
||||
Name: "marty",
|
||||
Age: 19,
|
||||
Birthday: time.Unix(1000000000, 0),
|
||||
Title: "mista",
|
||||
Tags: []string{"gopher", "belieber"},
|
||||
// has no birthday set to test handling of zero time
|
||||
Title: "mista",
|
||||
Tags: []string{"gopher", "belieber"},
|
||||
},
|
||||
&Person{
|
||||
Identifier: "b",
|
||||
|
@ -224,6 +224,22 @@ func TestIndex(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// test that 0 time doesn't get indexed
|
||||
endDate = "2010-01-01"
|
||||
dateRangeQuery = NewDateRangeQuery(nil, &endDate).SetField("birthday")
|
||||
searchRequest = NewSearchRequest(dateRangeQuery)
|
||||
searchResult, err = index.Search(searchRequest)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if searchResult.Total != uint64(1) {
|
||||
t.Errorf("expected 1 total hit for numeric range query, got %d", searchResult.Total)
|
||||
} else {
|
||||
if searchResult.Hits[0].ID != "b" {
|
||||
t.Errorf("expected top hit id 'b', got '%s'", searchResult.Hits[0].ID)
|
||||
}
|
||||
}
|
||||
|
||||
// test behavior of arrays
|
||||
// make sure we can successfully find by all elements in array
|
||||
termQuery = NewTermQuery("gopher").SetField("tags")
|
||||
|
|
|
@ -331,8 +331,12 @@ func (im *IndexMapping) processProperty(property interface{}, path []string, ind
|
|||
if dateTimeParser != nil {
|
||||
parsedDateTime, err := dateTimeParser.ParseDateTime(propertyValueString)
|
||||
if err != nil {
|
||||
field := document.NewDateTimeFieldWithIndexingOptions(fieldName, indexes, parsedDateTime, options)
|
||||
context.doc.AddField(field)
|
||||
field, err := document.NewDateTimeFieldWithIndexingOptions(fieldName, indexes, parsedDateTime, options)
|
||||
if err == nil {
|
||||
context.doc.AddField(field)
|
||||
} else {
|
||||
log.Printf("could not build date %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -356,8 +360,12 @@ func (im *IndexMapping) processProperty(property interface{}, path []string, ind
|
|||
context.doc.AddField(field)
|
||||
} else {
|
||||
// index as datetime
|
||||
field := document.NewDateTimeField(pathString, indexes, parsedDateTime)
|
||||
context.doc.AddField(field)
|
||||
field, err := document.NewDateTimeField(pathString, indexes, parsedDateTime)
|
||||
if err == nil {
|
||||
context.doc.AddField(field)
|
||||
} else {
|
||||
log.Printf("could not build date %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,16 +396,23 @@ func (im *IndexMapping) processProperty(property interface{}, path []string, ind
|
|||
fieldName := getFieldName(pathString, path, fieldMapping)
|
||||
if *fieldMapping.Type == "datetime" {
|
||||
options := fieldMapping.Options()
|
||||
field := document.NewDateTimeFieldWithIndexingOptions(fieldName, indexes, property, options)
|
||||
context.doc.AddField(field)
|
||||
field, err := document.NewDateTimeFieldWithIndexingOptions(fieldName, indexes, property, options)
|
||||
if err == nil {
|
||||
context.doc.AddField(field)
|
||||
} else {
|
||||
log.Printf("could not build date %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// automatic indexing behavior
|
||||
field := document.NewDateTimeField(pathString, indexes, property)
|
||||
context.doc.AddField(field)
|
||||
field, err := document.NewDateTimeField(pathString, indexes, property)
|
||||
if err == nil {
|
||||
context.doc.AddField(field)
|
||||
} else {
|
||||
log.Printf("could not build date %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
im.walkDocument(property, path, indexes, context)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue