suggest.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2012-2015 Oliver Eilhard. All rights reserved.
  2. // Use of this source code is governed by a MIT-license.
  3. // See http://olivere.mit-license.org/license.txt for details.
  4. package elastic
  5. import (
  6. "encoding/json"
  7. "fmt"
  8. "net/url"
  9. "strings"
  10. "github.com/olivere/elastic/uritemplates"
  11. )
  12. // SuggestService returns suggestions for text.
  13. type SuggestService struct {
  14. client *Client
  15. pretty bool
  16. routing string
  17. preference string
  18. indices []string
  19. suggesters []Suggester
  20. }
  21. func NewSuggestService(client *Client) *SuggestService {
  22. builder := &SuggestService{
  23. client: client,
  24. indices: make([]string, 0),
  25. suggesters: make([]Suggester, 0),
  26. }
  27. return builder
  28. }
  29. func (s *SuggestService) Index(index string) *SuggestService {
  30. s.indices = append(s.indices, index)
  31. return s
  32. }
  33. func (s *SuggestService) Indices(indices ...string) *SuggestService {
  34. s.indices = append(s.indices, indices...)
  35. return s
  36. }
  37. func (s *SuggestService) Pretty(pretty bool) *SuggestService {
  38. s.pretty = pretty
  39. return s
  40. }
  41. func (s *SuggestService) Routing(routing string) *SuggestService {
  42. s.routing = routing
  43. return s
  44. }
  45. func (s *SuggestService) Preference(preference string) *SuggestService {
  46. s.preference = preference
  47. return s
  48. }
  49. func (s *SuggestService) Suggester(suggester Suggester) *SuggestService {
  50. s.suggesters = append(s.suggesters, suggester)
  51. return s
  52. }
  53. func (s *SuggestService) Do() (SuggestResult, error) {
  54. // Build url
  55. path := "/"
  56. // Indices part
  57. indexPart := make([]string, 0)
  58. for _, index := range s.indices {
  59. index, err := uritemplates.Expand("{index}", map[string]string{
  60. "index": index,
  61. })
  62. if err != nil {
  63. return nil, err
  64. }
  65. indexPart = append(indexPart, index)
  66. }
  67. path += strings.Join(indexPart, ",")
  68. // Suggest
  69. path += "/_suggest"
  70. // Parameters
  71. params := make(url.Values)
  72. if s.pretty {
  73. params.Set("pretty", fmt.Sprintf("%v", s.pretty))
  74. }
  75. if s.routing != "" {
  76. params.Set("routing", s.routing)
  77. }
  78. if s.preference != "" {
  79. params.Set("preference", s.preference)
  80. }
  81. // Set body
  82. body := make(map[string]interface{})
  83. for _, s := range s.suggesters {
  84. body[s.Name()] = s.Source(false)
  85. }
  86. // Get response
  87. res, err := s.client.PerformRequest("POST", path, params, body)
  88. if err != nil {
  89. return nil, err
  90. }
  91. // There is a _shard object that cannot be deserialized.
  92. // So we use json.RawMessage instead.
  93. var suggestions map[string]*json.RawMessage
  94. if err := json.Unmarshal(res.Body, &suggestions); err != nil {
  95. return nil, err
  96. }
  97. ret := make(SuggestResult)
  98. for name, result := range suggestions {
  99. if name != "_shards" {
  100. var s []Suggestion
  101. if err := json.Unmarshal(*result, &s); err != nil {
  102. return nil, err
  103. }
  104. ret[name] = s
  105. }
  106. }
  107. return ret, nil
  108. }
  109. type SuggestResult map[string][]Suggestion
  110. type Suggestion struct {
  111. Text string `json:"text"`
  112. Offset int `json:"offset"`
  113. Length int `json:"length"`
  114. Options []suggestionOption `json:"options"`
  115. }
  116. type suggestionOption struct {
  117. Text string `json:"text"`
  118. Score float32 `json:"score"`
  119. Freq int `json:"freq"`
  120. Payload interface{} `json:"payload"`
  121. }