mget.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // Copyright 2012-present 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. "context"
  7. "fmt"
  8. "net/url"
  9. "strings"
  10. )
  11. // MgetService allows to get multiple documents based on an index,
  12. // type (optional) and id (possibly routing). The response includes
  13. // a docs array with all the fetched documents, each element similar
  14. // in structure to a document provided by the Get API.
  15. //
  16. // See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/docs-multi-get.html
  17. // for details.
  18. type MgetService struct {
  19. client *Client
  20. pretty bool
  21. preference string
  22. realtime *bool
  23. refresh string
  24. routing string
  25. storedFields []string
  26. items []*MultiGetItem
  27. }
  28. // NewMgetService initializes a new Multi GET API request call.
  29. func NewMgetService(client *Client) *MgetService {
  30. builder := &MgetService{
  31. client: client,
  32. }
  33. return builder
  34. }
  35. // Preference specifies the node or shard the operation should be performed
  36. // on (default: random).
  37. func (s *MgetService) Preference(preference string) *MgetService {
  38. s.preference = preference
  39. return s
  40. }
  41. // Refresh the shard containing the document before performing the operation.
  42. func (s *MgetService) Refresh(refresh string) *MgetService {
  43. s.refresh = refresh
  44. return s
  45. }
  46. // Realtime specifies whether to perform the operation in realtime or search mode.
  47. func (s *MgetService) Realtime(realtime bool) *MgetService {
  48. s.realtime = &realtime
  49. return s
  50. }
  51. // Routing is the specific routing value.
  52. func (s *MgetService) Routing(routing string) *MgetService {
  53. s.routing = routing
  54. return s
  55. }
  56. // StoredFields is a list of fields to return in the response.
  57. func (s *MgetService) StoredFields(storedFields ...string) *MgetService {
  58. s.storedFields = append(s.storedFields, storedFields...)
  59. return s
  60. }
  61. // Pretty indicates that the JSON response be indented and human readable.
  62. func (s *MgetService) Pretty(pretty bool) *MgetService {
  63. s.pretty = pretty
  64. return s
  65. }
  66. // Add an item to the request.
  67. func (s *MgetService) Add(items ...*MultiGetItem) *MgetService {
  68. s.items = append(s.items, items...)
  69. return s
  70. }
  71. // Source returns the request body, which will be serialized into JSON.
  72. func (s *MgetService) Source() (interface{}, error) {
  73. source := make(map[string]interface{})
  74. items := make([]interface{}, len(s.items))
  75. for i, item := range s.items {
  76. src, err := item.Source()
  77. if err != nil {
  78. return nil, err
  79. }
  80. items[i] = src
  81. }
  82. source["docs"] = items
  83. return source, nil
  84. }
  85. // Do executes the request.
  86. func (s *MgetService) Do(ctx context.Context) (*MgetResponse, error) {
  87. // Build url
  88. path := "/_mget"
  89. params := make(url.Values)
  90. if s.realtime != nil {
  91. params.Add("realtime", fmt.Sprintf("%v", *s.realtime))
  92. }
  93. if s.preference != "" {
  94. params.Add("preference", s.preference)
  95. }
  96. if s.refresh != "" {
  97. params.Add("refresh", s.refresh)
  98. }
  99. if s.routing != "" {
  100. params.Set("routing", s.routing)
  101. }
  102. if len(s.storedFields) > 0 {
  103. params.Set("stored_fields", strings.Join(s.storedFields, ","))
  104. }
  105. // Set body
  106. body, err := s.Source()
  107. if err != nil {
  108. return nil, err
  109. }
  110. // Get response
  111. res, err := s.client.PerformRequest(ctx, "GET", path, params, body)
  112. if err != nil {
  113. return nil, err
  114. }
  115. // Return result
  116. ret := new(MgetResponse)
  117. if err := s.client.decoder.Decode(res.Body, ret); err != nil {
  118. return nil, err
  119. }
  120. return ret, nil
  121. }
  122. // -- Multi Get Item --
  123. // MultiGetItem is a single document to retrieve via the MgetService.
  124. type MultiGetItem struct {
  125. index string
  126. typ string
  127. id string
  128. routing string
  129. storedFields []string
  130. version *int64 // see org.elasticsearch.common.lucene.uid.Versions
  131. versionType string // see org.elasticsearch.index.VersionType
  132. fsc *FetchSourceContext
  133. }
  134. // NewMultiGetItem initializes a new, single item for a Multi GET request.
  135. func NewMultiGetItem() *MultiGetItem {
  136. return &MultiGetItem{}
  137. }
  138. // Index specifies the index name.
  139. func (item *MultiGetItem) Index(index string) *MultiGetItem {
  140. item.index = index
  141. return item
  142. }
  143. // Type specifies the type name.
  144. func (item *MultiGetItem) Type(typ string) *MultiGetItem {
  145. item.typ = typ
  146. return item
  147. }
  148. // Id specifies the identifier of the document.
  149. func (item *MultiGetItem) Id(id string) *MultiGetItem {
  150. item.id = id
  151. return item
  152. }
  153. // Routing is the specific routing value.
  154. func (item *MultiGetItem) Routing(routing string) *MultiGetItem {
  155. item.routing = routing
  156. return item
  157. }
  158. // StoredFields is a list of fields to return in the response.
  159. func (item *MultiGetItem) StoredFields(storedFields ...string) *MultiGetItem {
  160. item.storedFields = append(item.storedFields, storedFields...)
  161. return item
  162. }
  163. // Version can be MatchAny (-3), MatchAnyPre120 (0), NotFound (-1),
  164. // or NotSet (-2). These are specified in org.elasticsearch.common.lucene.uid.Versions.
  165. // The default in Elasticsearch is MatchAny (-3).
  166. func (item *MultiGetItem) Version(version int64) *MultiGetItem {
  167. item.version = &version
  168. return item
  169. }
  170. // VersionType can be "internal", "external", "external_gt", "external_gte",
  171. // or "force". See org.elasticsearch.index.VersionType in Elasticsearch source.
  172. // It is "internal" by default.
  173. func (item *MultiGetItem) VersionType(versionType string) *MultiGetItem {
  174. item.versionType = versionType
  175. return item
  176. }
  177. // FetchSource allows to specify source filtering.
  178. func (item *MultiGetItem) FetchSource(fetchSourceContext *FetchSourceContext) *MultiGetItem {
  179. item.fsc = fetchSourceContext
  180. return item
  181. }
  182. // Source returns the serialized JSON to be sent to Elasticsearch as
  183. // part of a MultiGet search.
  184. func (item *MultiGetItem) Source() (interface{}, error) {
  185. source := make(map[string]interface{})
  186. source["_id"] = item.id
  187. if item.index != "" {
  188. source["_index"] = item.index
  189. }
  190. if item.typ != "" {
  191. source["_type"] = item.typ
  192. }
  193. if item.fsc != nil {
  194. src, err := item.fsc.Source()
  195. if err != nil {
  196. return nil, err
  197. }
  198. source["_source"] = src
  199. }
  200. if item.routing != "" {
  201. source["_routing"] = item.routing
  202. }
  203. if len(item.storedFields) > 0 {
  204. source["stored_fields"] = strings.Join(item.storedFields, ",")
  205. }
  206. if item.version != nil {
  207. source["version"] = fmt.Sprintf("%d", *item.version)
  208. }
  209. if item.versionType != "" {
  210. source["version_type"] = item.versionType
  211. }
  212. return source, nil
  213. }
  214. // -- Result of a Multi Get request.
  215. // MgetResponse is the outcome of a Multi GET API request.
  216. type MgetResponse struct {
  217. Docs []*GetResult `json:"docs,omitempty"`
  218. }