本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.5KB

  1. // Copyright (c) 2014 Couchbase, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package query
  15. import (
  16. "encoding/json"
  17. "fmt"
  18. "math"
  19. "time"
  20. "github.com/blevesearch/bleve/analysis/datetime/optional"
  21. "github.com/blevesearch/bleve/index"
  22. "github.com/blevesearch/bleve/mapping"
  23. "github.com/blevesearch/bleve/numeric"
  24. "github.com/blevesearch/bleve/registry"
  25. "github.com/blevesearch/bleve/search"
  26. "github.com/blevesearch/bleve/search/searcher"
  27. )
  28. // QueryDateTimeParser controls the default query date time parser
  29. var QueryDateTimeParser = optional.Name
  30. // QueryDateTimeFormat controls the format when Marshaling to JSON
  31. var QueryDateTimeFormat = time.RFC3339
  32. var cache = registry.NewCache()
  33. type BleveQueryTime struct {
  34. time.Time
  35. }
  36. func queryTimeFromString(t string) (time.Time, error) {
  37. dateTimeParser, err := cache.DateTimeParserNamed(QueryDateTimeParser)
  38. if err != nil {
  39. return time.Time{}, err
  40. }
  41. rv, err := dateTimeParser.ParseDateTime(t)
  42. if err != nil {
  43. return time.Time{}, err
  44. }
  45. return rv, nil
  46. }
  47. func (t *BleveQueryTime) MarshalJSON() ([]byte, error) {
  48. tt := time.Time(t.Time)
  49. return []byte("\"" + tt.Format(QueryDateTimeFormat) + "\""), nil
  50. }
  51. func (t *BleveQueryTime) UnmarshalJSON(data []byte) error {
  52. var timeString string
  53. err := json.Unmarshal(data, &timeString)
  54. if err != nil {
  55. return err
  56. }
  57. dateTimeParser, err := cache.DateTimeParserNamed(QueryDateTimeParser)
  58. if err != nil {
  59. return err
  60. }
  61. t.Time, err = dateTimeParser.ParseDateTime(timeString)
  62. if err != nil {
  63. return err
  64. }
  65. return nil
  66. }
  67. type DateRangeQuery struct {
  68. Start BleveQueryTime `json:"start,omitempty"`
  69. End BleveQueryTime `json:"end,omitempty"`
  70. InclusiveStart *bool `json:"inclusive_start,omitempty"`
  71. InclusiveEnd *bool `json:"inclusive_end,omitempty"`
  72. FieldVal string `json:"field,omitempty"`
  73. BoostVal *Boost `json:"boost,omitempty"`
  74. }
  75. // NewDateRangeQuery creates a new Query for ranges
  76. // of date values.
  77. // Date strings are parsed using the DateTimeParser configured in the
  78. // top-level config.QueryDateTimeParser
  79. // Either, but not both endpoints can be nil.
  80. func NewDateRangeQuery(start, end time.Time) *DateRangeQuery {
  81. return NewDateRangeInclusiveQuery(start, end, nil, nil)
  82. }
  83. // NewDateRangeInclusiveQuery creates a new Query for ranges
  84. // of date values.
  85. // Date strings are parsed using the DateTimeParser configured in the
  86. // top-level config.QueryDateTimeParser
  87. // Either, but not both endpoints can be nil.
  88. // startInclusive and endInclusive control inclusion of the endpoints.
  89. func NewDateRangeInclusiveQuery(start, end time.Time, startInclusive, endInclusive *bool) *DateRangeQuery {
  90. return &DateRangeQuery{
  91. Start: BleveQueryTime{start},
  92. End: BleveQueryTime{end},
  93. InclusiveStart: startInclusive,
  94. InclusiveEnd: endInclusive,
  95. }
  96. }
  97. func (q *DateRangeQuery) SetBoost(b float64) {
  98. boost := Boost(b)
  99. q.BoostVal = &boost
  100. }
  101. func (q *DateRangeQuery) Boost() float64 {
  102. return q.BoostVal.Value()
  103. }
  104. func (q *DateRangeQuery) SetField(f string) {
  105. q.FieldVal = f
  106. }
  107. func (q *DateRangeQuery) Field() string {
  108. return q.FieldVal
  109. }
  110. func (q *DateRangeQuery) Searcher(i index.IndexReader, m mapping.IndexMapping, options search.SearcherOptions) (search.Searcher, error) {
  111. min, max, err := q.parseEndpoints()
  112. if err != nil {
  113. return nil, err
  114. }
  115. field := q.FieldVal
  116. if q.FieldVal == "" {
  117. field = m.DefaultSearchField()
  118. }
  119. return searcher.NewNumericRangeSearcher(i, min, max, q.InclusiveStart, q.InclusiveEnd, field, q.BoostVal.Value(), options)
  120. }
  121. func (q *DateRangeQuery) parseEndpoints() (*float64, *float64, error) {
  122. min := math.Inf(-1)
  123. max := math.Inf(1)
  124. if !q.Start.IsZero() {
  125. min = numeric.Int64ToFloat64(q.Start.UnixNano())
  126. }
  127. if !q.End.IsZero() {
  128. max = numeric.Int64ToFloat64(q.End.UnixNano())
  129. }
  130. return &min, &max, nil
  131. }
  132. func (q *DateRangeQuery) Validate() error {
  133. if q.Start.IsZero() && q.End.IsZero() {
  134. return fmt.Errorf("must specify start or end")
  135. }
  136. _, _, err := q.parseEndpoints()
  137. if err != nil {
  138. return err
  139. }
  140. return nil
  141. }
上海开阖软件有限公司 沪ICP备12045867号-1