sort.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  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 search
  15. import (
  16. "bytes"
  17. "encoding/json"
  18. "fmt"
  19. "math"
  20. "sort"
  21. "strings"
  22. "github.com/blevesearch/bleve/geo"
  23. "github.com/blevesearch/bleve/numeric"
  24. )
  25. var HighTerm = strings.Repeat(string([]byte{0xff}), 10)
  26. var LowTerm = string([]byte{0x00})
  27. type SearchSort interface {
  28. UpdateVisitor(field string, term []byte)
  29. Value(a *DocumentMatch) string
  30. Descending() bool
  31. RequiresDocID() bool
  32. RequiresScoring() bool
  33. RequiresFields() []string
  34. Reverse()
  35. Copy() SearchSort
  36. }
  37. func ParseSearchSortObj(input map[string]interface{}) (SearchSort, error) {
  38. descending, ok := input["desc"].(bool)
  39. by, ok := input["by"].(string)
  40. if !ok {
  41. return nil, fmt.Errorf("search sort must specify by")
  42. }
  43. switch by {
  44. case "id":
  45. return &SortDocID{
  46. Desc: descending,
  47. }, nil
  48. case "score":
  49. return &SortScore{
  50. Desc: descending,
  51. }, nil
  52. case "geo_distance":
  53. field, ok := input["field"].(string)
  54. if !ok {
  55. return nil, fmt.Errorf("search sort mode geo_distance must specify field")
  56. }
  57. lon, lat, foundLocation := geo.ExtractGeoPoint(input["location"])
  58. if !foundLocation {
  59. return nil, fmt.Errorf("unable to parse geo_distance location")
  60. }
  61. rvd := &SortGeoDistance{
  62. Field: field,
  63. Desc: descending,
  64. Lon: lon,
  65. Lat: lat,
  66. unitMult: 1.0,
  67. }
  68. if distUnit, ok := input["unit"].(string); ok {
  69. var err error
  70. rvd.unitMult, err = geo.ParseDistanceUnit(distUnit)
  71. if err != nil {
  72. return nil, err
  73. }
  74. rvd.Unit = distUnit
  75. }
  76. return rvd, nil
  77. case "field":
  78. field, ok := input["field"].(string)
  79. if !ok {
  80. return nil, fmt.Errorf("search sort mode field must specify field")
  81. }
  82. rv := &SortField{
  83. Field: field,
  84. Desc: descending,
  85. }
  86. typ, ok := input["type"].(string)
  87. if ok {
  88. switch typ {
  89. case "auto":
  90. rv.Type = SortFieldAuto
  91. case "string":
  92. rv.Type = SortFieldAsString
  93. case "number":
  94. rv.Type = SortFieldAsNumber
  95. case "date":
  96. rv.Type = SortFieldAsDate
  97. default:
  98. return nil, fmt.Errorf("unknown sort field type: %s", typ)
  99. }
  100. }
  101. mode, ok := input["mode"].(string)
  102. if ok {
  103. switch mode {
  104. case "default":
  105. rv.Mode = SortFieldDefault
  106. case "min":
  107. rv.Mode = SortFieldMin
  108. case "max":
  109. rv.Mode = SortFieldMax
  110. default:
  111. return nil, fmt.Errorf("unknown sort field mode: %s", mode)
  112. }
  113. }
  114. missing, ok := input["missing"].(string)
  115. if ok {
  116. switch missing {
  117. case "first":
  118. rv.Missing = SortFieldMissingFirst
  119. case "last":
  120. rv.Missing = SortFieldMissingLast
  121. default:
  122. return nil, fmt.Errorf("unknown sort field missing: %s", missing)
  123. }
  124. }
  125. return rv, nil
  126. }
  127. return nil, fmt.Errorf("unknown search sort by: %s", by)
  128. }
  129. func ParseSearchSortString(input string) SearchSort {
  130. descending := false
  131. if strings.HasPrefix(input, "-") {
  132. descending = true
  133. input = input[1:]
  134. } else if strings.HasPrefix(input, "+") {
  135. input = input[1:]
  136. }
  137. if input == "_id" {
  138. return &SortDocID{
  139. Desc: descending,
  140. }
  141. } else if input == "_score" {
  142. return &SortScore{
  143. Desc: descending,
  144. }
  145. }
  146. return &SortField{
  147. Field: input,
  148. Desc: descending,
  149. }
  150. }
  151. func ParseSearchSortJSON(input json.RawMessage) (SearchSort, error) {
  152. // first try to parse it as string
  153. var sortString string
  154. err := json.Unmarshal(input, &sortString)
  155. if err != nil {
  156. var sortObj map[string]interface{}
  157. err = json.Unmarshal(input, &sortObj)
  158. if err != nil {
  159. return nil, err
  160. }
  161. return ParseSearchSortObj(sortObj)
  162. }
  163. return ParseSearchSortString(sortString), nil
  164. }
  165. func ParseSortOrderStrings(in []string) SortOrder {
  166. rv := make(SortOrder, 0, len(in))
  167. for _, i := range in {
  168. ss := ParseSearchSortString(i)
  169. rv = append(rv, ss)
  170. }
  171. return rv
  172. }
  173. func ParseSortOrderJSON(in []json.RawMessage) (SortOrder, error) {
  174. rv := make(SortOrder, 0, len(in))
  175. for _, i := range in {
  176. ss, err := ParseSearchSortJSON(i)
  177. if err != nil {
  178. return nil, err
  179. }
  180. rv = append(rv, ss)
  181. }
  182. return rv, nil
  183. }
  184. type SortOrder []SearchSort
  185. func (so SortOrder) Value(doc *DocumentMatch) {
  186. for _, soi := range so {
  187. doc.Sort = append(doc.Sort, soi.Value(doc))
  188. }
  189. }
  190. func (so SortOrder) UpdateVisitor(field string, term []byte) {
  191. for _, soi := range so {
  192. soi.UpdateVisitor(field, term)
  193. }
  194. }
  195. func (so SortOrder) Copy() SortOrder {
  196. rv := make(SortOrder, len(so))
  197. for i, soi := range so {
  198. rv[i] = soi.Copy()
  199. }
  200. return rv
  201. }
  202. // Compare will compare two document matches using the specified sort order
  203. // if both are numbers, we avoid converting back to term
  204. func (so SortOrder) Compare(cachedScoring, cachedDesc []bool, i, j *DocumentMatch) int {
  205. // compare the documents on all search sorts until a differences is found
  206. for x := range so {
  207. c := 0
  208. if cachedScoring[x] {
  209. if i.Score < j.Score {
  210. c = -1
  211. } else if i.Score > j.Score {
  212. c = 1
  213. }
  214. } else {
  215. iVal := i.Sort[x]
  216. jVal := j.Sort[x]
  217. c = strings.Compare(iVal, jVal)
  218. }
  219. if c == 0 {
  220. continue
  221. }
  222. if cachedDesc[x] {
  223. c = -c
  224. }
  225. return c
  226. }
  227. // if they are the same at this point, impose order based on index natural sort order
  228. if i.HitNumber == j.HitNumber {
  229. return 0
  230. } else if i.HitNumber > j.HitNumber {
  231. return 1
  232. }
  233. return -1
  234. }
  235. func (so SortOrder) RequiresScore() bool {
  236. for _, soi := range so {
  237. if soi.RequiresScoring() {
  238. return true
  239. }
  240. }
  241. return false
  242. }
  243. func (so SortOrder) RequiresDocID() bool {
  244. for _, soi := range so {
  245. if soi.RequiresDocID() {
  246. return true
  247. }
  248. }
  249. return false
  250. }
  251. func (so SortOrder) RequiredFields() []string {
  252. var rv []string
  253. for _, soi := range so {
  254. rv = append(rv, soi.RequiresFields()...)
  255. }
  256. return rv
  257. }
  258. func (so SortOrder) CacheIsScore() []bool {
  259. rv := make([]bool, 0, len(so))
  260. for _, soi := range so {
  261. rv = append(rv, soi.RequiresScoring())
  262. }
  263. return rv
  264. }
  265. func (so SortOrder) CacheDescending() []bool {
  266. rv := make([]bool, 0, len(so))
  267. for _, soi := range so {
  268. rv = append(rv, soi.Descending())
  269. }
  270. return rv
  271. }
  272. func (so SortOrder) Reverse() {
  273. for _, soi := range so {
  274. soi.Reverse()
  275. }
  276. }
  277. // SortFieldType lets you control some internal sort behavior
  278. // normally leaving this to the zero-value of SortFieldAuto is fine
  279. type SortFieldType int
  280. const (
  281. // SortFieldAuto applies heuristics attempt to automatically sort correctly
  282. SortFieldAuto SortFieldType = iota
  283. // SortFieldAsString forces sort as string (no prefix coded terms removed)
  284. SortFieldAsString
  285. // SortFieldAsNumber forces sort as string (prefix coded terms with shift > 0 removed)
  286. SortFieldAsNumber
  287. // SortFieldAsDate forces sort as string (prefix coded terms with shift > 0 removed)
  288. SortFieldAsDate
  289. )
  290. // SortFieldMode describes the behavior if the field has multiple values
  291. type SortFieldMode int
  292. const (
  293. // SortFieldDefault uses the first (or only) value, this is the default zero-value
  294. SortFieldDefault SortFieldMode = iota // FIXME name is confusing
  295. // SortFieldMin uses the minimum value
  296. SortFieldMin
  297. // SortFieldMax uses the maximum value
  298. SortFieldMax
  299. )
  300. // SortFieldMissing controls where documents missing a field value should be sorted
  301. type SortFieldMissing int
  302. const (
  303. // SortFieldMissingLast sorts documents missing a field at the end
  304. SortFieldMissingLast SortFieldMissing = iota
  305. // SortFieldMissingFirst sorts documents missing a field at the beginning
  306. SortFieldMissingFirst
  307. )
  308. // SortField will sort results by the value of a stored field
  309. // Field is the name of the field
  310. // Descending reverse the sort order (default false)
  311. // Type allows forcing of string/number/date behavior (default auto)
  312. // Mode controls behavior for multi-values fields (default first)
  313. // Missing controls behavior of missing values (default last)
  314. type SortField struct {
  315. Field string
  316. Desc bool
  317. Type SortFieldType
  318. Mode SortFieldMode
  319. Missing SortFieldMissing
  320. values [][]byte
  321. tmp [][]byte
  322. }
  323. // UpdateVisitor notifies this sort field that in this document
  324. // this field has the specified term
  325. func (s *SortField) UpdateVisitor(field string, term []byte) {
  326. if field == s.Field {
  327. s.values = append(s.values, term)
  328. }
  329. }
  330. // Value returns the sort value of the DocumentMatch
  331. // it also resets the state of this SortField for
  332. // processing the next document
  333. func (s *SortField) Value(i *DocumentMatch) string {
  334. iTerms := s.filterTermsByType(s.values)
  335. iTerm := s.filterTermsByMode(iTerms)
  336. s.values = s.values[:0]
  337. return iTerm
  338. }
  339. // Descending determines the order of the sort
  340. func (s *SortField) Descending() bool {
  341. return s.Desc
  342. }
  343. func (s *SortField) filterTermsByMode(terms [][]byte) string {
  344. if len(terms) == 1 || (len(terms) > 1 && s.Mode == SortFieldDefault) {
  345. return string(terms[0])
  346. } else if len(terms) > 1 {
  347. switch s.Mode {
  348. case SortFieldMin:
  349. sort.Sort(BytesSlice(terms))
  350. return string(terms[0])
  351. case SortFieldMax:
  352. sort.Sort(BytesSlice(terms))
  353. return string(terms[len(terms)-1])
  354. }
  355. }
  356. // handle missing terms
  357. if s.Missing == SortFieldMissingLast {
  358. if s.Desc {
  359. return LowTerm
  360. }
  361. return HighTerm
  362. }
  363. if s.Desc {
  364. return HighTerm
  365. }
  366. return LowTerm
  367. }
  368. // filterTermsByType attempts to make one pass on the terms
  369. // if we are in auto-mode AND all the terms look like prefix-coded numbers
  370. // return only the terms which had shift of 0
  371. // if we are in explicit number or date mode, return only valid
  372. // prefix coded numbers with shift of 0
  373. func (s *SortField) filterTermsByType(terms [][]byte) [][]byte {
  374. stype := s.Type
  375. if stype == SortFieldAuto {
  376. allTermsPrefixCoded := true
  377. termsWithShiftZero := s.tmp[:0]
  378. for _, term := range terms {
  379. valid, shift := numeric.ValidPrefixCodedTermBytes(term)
  380. if valid && shift == 0 {
  381. termsWithShiftZero = append(termsWithShiftZero, term)
  382. } else if !valid {
  383. allTermsPrefixCoded = false
  384. }
  385. }
  386. if allTermsPrefixCoded {
  387. terms = termsWithShiftZero
  388. s.tmp = termsWithShiftZero[:0]
  389. }
  390. } else if stype == SortFieldAsNumber || stype == SortFieldAsDate {
  391. termsWithShiftZero := s.tmp[:0]
  392. for _, term := range terms {
  393. valid, shift := numeric.ValidPrefixCodedTermBytes(term)
  394. if valid && shift == 0 {
  395. termsWithShiftZero = append(termsWithShiftZero, term)
  396. }
  397. }
  398. terms = termsWithShiftZero
  399. s.tmp = termsWithShiftZero[:0]
  400. }
  401. return terms
  402. }
  403. // RequiresDocID says this SearchSort does not require the DocID be loaded
  404. func (s *SortField) RequiresDocID() bool { return false }
  405. // RequiresScoring says this SearchStore does not require scoring
  406. func (s *SortField) RequiresScoring() bool { return false }
  407. // RequiresFields says this SearchStore requires the specified stored field
  408. func (s *SortField) RequiresFields() []string { return []string{s.Field} }
  409. func (s *SortField) MarshalJSON() ([]byte, error) {
  410. // see if simple format can be used
  411. if s.Missing == SortFieldMissingLast &&
  412. s.Mode == SortFieldDefault &&
  413. s.Type == SortFieldAuto {
  414. if s.Desc {
  415. return json.Marshal("-" + s.Field)
  416. }
  417. return json.Marshal(s.Field)
  418. }
  419. sfm := map[string]interface{}{
  420. "by": "field",
  421. "field": s.Field,
  422. }
  423. if s.Desc {
  424. sfm["desc"] = true
  425. }
  426. if s.Missing > SortFieldMissingLast {
  427. switch s.Missing {
  428. case SortFieldMissingFirst:
  429. sfm["missing"] = "first"
  430. }
  431. }
  432. if s.Mode > SortFieldDefault {
  433. switch s.Mode {
  434. case SortFieldMin:
  435. sfm["mode"] = "min"
  436. case SortFieldMax:
  437. sfm["mode"] = "max"
  438. }
  439. }
  440. if s.Type > SortFieldAuto {
  441. switch s.Type {
  442. case SortFieldAsString:
  443. sfm["type"] = "string"
  444. case SortFieldAsNumber:
  445. sfm["type"] = "number"
  446. case SortFieldAsDate:
  447. sfm["type"] = "date"
  448. }
  449. }
  450. return json.Marshal(sfm)
  451. }
  452. func (s *SortField) Copy() SearchSort {
  453. rv := *s
  454. return &rv
  455. }
  456. func (s *SortField) Reverse() {
  457. s.Desc = !s.Desc
  458. if s.Missing == SortFieldMissingFirst {
  459. s.Missing = SortFieldMissingLast
  460. } else {
  461. s.Missing = SortFieldMissingFirst
  462. }
  463. }
  464. // SortDocID will sort results by the document identifier
  465. type SortDocID struct {
  466. Desc bool
  467. }
  468. // UpdateVisitor is a no-op for SortDocID as it's value
  469. // is not dependent on any field terms
  470. func (s *SortDocID) UpdateVisitor(field string, term []byte) {
  471. }
  472. // Value returns the sort value of the DocumentMatch
  473. func (s *SortDocID) Value(i *DocumentMatch) string {
  474. return i.ID
  475. }
  476. // Descending determines the order of the sort
  477. func (s *SortDocID) Descending() bool {
  478. return s.Desc
  479. }
  480. // RequiresDocID says this SearchSort does require the DocID be loaded
  481. func (s *SortDocID) RequiresDocID() bool { return true }
  482. // RequiresScoring says this SearchStore does not require scoring
  483. func (s *SortDocID) RequiresScoring() bool { return false }
  484. // RequiresFields says this SearchStore does not require any stored fields
  485. func (s *SortDocID) RequiresFields() []string { return nil }
  486. func (s *SortDocID) MarshalJSON() ([]byte, error) {
  487. if s.Desc {
  488. return json.Marshal("-_id")
  489. }
  490. return json.Marshal("_id")
  491. }
  492. func (s *SortDocID) Copy() SearchSort {
  493. rv := *s
  494. return &rv
  495. }
  496. func (s *SortDocID) Reverse() {
  497. s.Desc = !s.Desc
  498. }
  499. // SortScore will sort results by the document match score
  500. type SortScore struct {
  501. Desc bool
  502. }
  503. // UpdateVisitor is a no-op for SortScore as it's value
  504. // is not dependent on any field terms
  505. func (s *SortScore) UpdateVisitor(field string, term []byte) {
  506. }
  507. // Value returns the sort value of the DocumentMatch
  508. func (s *SortScore) Value(i *DocumentMatch) string {
  509. return "_score"
  510. }
  511. // Descending determines the order of the sort
  512. func (s *SortScore) Descending() bool {
  513. return s.Desc
  514. }
  515. // RequiresDocID says this SearchSort does not require the DocID be loaded
  516. func (s *SortScore) RequiresDocID() bool { return false }
  517. // RequiresScoring says this SearchStore does require scoring
  518. func (s *SortScore) RequiresScoring() bool { return true }
  519. // RequiresFields says this SearchStore does not require any store fields
  520. func (s *SortScore) RequiresFields() []string { return nil }
  521. func (s *SortScore) MarshalJSON() ([]byte, error) {
  522. if s.Desc {
  523. return json.Marshal("-_score")
  524. }
  525. return json.Marshal("_score")
  526. }
  527. func (s *SortScore) Copy() SearchSort {
  528. rv := *s
  529. return &rv
  530. }
  531. func (s *SortScore) Reverse() {
  532. s.Desc = !s.Desc
  533. }
  534. var maxDistance = string(numeric.MustNewPrefixCodedInt64(math.MaxInt64, 0))
  535. // NewSortGeoDistance creates SearchSort instance for sorting documents by
  536. // their distance from the specified point.
  537. func NewSortGeoDistance(field, unit string, lon, lat float64, desc bool) (
  538. *SortGeoDistance, error) {
  539. rv := &SortGeoDistance{
  540. Field: field,
  541. Desc: desc,
  542. Unit: unit,
  543. Lon: lon,
  544. Lat: lat,
  545. }
  546. var err error
  547. rv.unitMult, err = geo.ParseDistanceUnit(unit)
  548. if err != nil {
  549. return nil, err
  550. }
  551. return rv, nil
  552. }
  553. // SortGeoDistance will sort results by the distance of an
  554. // indexed geo point, from the provided location.
  555. // Field is the name of the field
  556. // Descending reverse the sort order (default false)
  557. type SortGeoDistance struct {
  558. Field string
  559. Desc bool
  560. Unit string
  561. values []string
  562. Lon float64
  563. Lat float64
  564. unitMult float64
  565. }
  566. // UpdateVisitor notifies this sort field that in this document
  567. // this field has the specified term
  568. func (s *SortGeoDistance) UpdateVisitor(field string, term []byte) {
  569. if field == s.Field {
  570. s.values = append(s.values, string(term))
  571. }
  572. }
  573. // Value returns the sort value of the DocumentMatch
  574. // it also resets the state of this SortField for
  575. // processing the next document
  576. func (s *SortGeoDistance) Value(i *DocumentMatch) string {
  577. iTerms := s.filterTermsByType(s.values)
  578. iTerm := s.filterTermsByMode(iTerms)
  579. s.values = s.values[:0]
  580. if iTerm == "" {
  581. return maxDistance
  582. }
  583. i64, err := numeric.PrefixCoded(iTerm).Int64()
  584. if err != nil {
  585. return maxDistance
  586. }
  587. docLon := geo.MortonUnhashLon(uint64(i64))
  588. docLat := geo.MortonUnhashLat(uint64(i64))
  589. dist := geo.Haversin(s.Lon, s.Lat, docLon, docLat)
  590. // dist is returned in km, so convert to m
  591. dist *= 1000
  592. if s.unitMult != 0 {
  593. dist /= s.unitMult
  594. }
  595. distInt64 := numeric.Float64ToInt64(dist)
  596. return string(numeric.MustNewPrefixCodedInt64(distInt64, 0))
  597. }
  598. // Descending determines the order of the sort
  599. func (s *SortGeoDistance) Descending() bool {
  600. return s.Desc
  601. }
  602. func (s *SortGeoDistance) filterTermsByMode(terms []string) string {
  603. if len(terms) >= 1 {
  604. return terms[0]
  605. }
  606. return ""
  607. }
  608. // filterTermsByType attempts to make one pass on the terms
  609. // return only valid prefix coded numbers with shift of 0
  610. func (s *SortGeoDistance) filterTermsByType(terms []string) []string {
  611. var termsWithShiftZero []string
  612. for _, term := range terms {
  613. valid, shift := numeric.ValidPrefixCodedTerm(term)
  614. if valid && shift == 0 {
  615. termsWithShiftZero = append(termsWithShiftZero, term)
  616. }
  617. }
  618. return termsWithShiftZero
  619. }
  620. // RequiresDocID says this SearchSort does not require the DocID be loaded
  621. func (s *SortGeoDistance) RequiresDocID() bool { return false }
  622. // RequiresScoring says this SearchStore does not require scoring
  623. func (s *SortGeoDistance) RequiresScoring() bool { return false }
  624. // RequiresFields says this SearchStore requires the specified stored field
  625. func (s *SortGeoDistance) RequiresFields() []string { return []string{s.Field} }
  626. func (s *SortGeoDistance) MarshalJSON() ([]byte, error) {
  627. sfm := map[string]interface{}{
  628. "by": "geo_distance",
  629. "field": s.Field,
  630. "location": map[string]interface{}{
  631. "lon": s.Lon,
  632. "lat": s.Lat,
  633. },
  634. }
  635. if s.Unit != "" {
  636. sfm["unit"] = s.Unit
  637. }
  638. if s.Desc {
  639. sfm["desc"] = true
  640. }
  641. return json.Marshal(sfm)
  642. }
  643. func (s *SortGeoDistance) Copy() SearchSort {
  644. rv := *s
  645. return &rv
  646. }
  647. func (s *SortGeoDistance) Reverse() {
  648. s.Desc = !s.Desc
  649. }
  650. type BytesSlice [][]byte
  651. func (p BytesSlice) Len() int { return len(p) }
  652. func (p BytesSlice) Less(i, j int) bool { return bytes.Compare(p[i], p[j]) < 0 }
  653. func (p BytesSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }