get.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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. "encoding/json"
  8. "fmt"
  9. "net/url"
  10. "strings"
  11. "gopkg.in/olivere/elastic.v5/uritemplates"
  12. )
  13. // GetService allows to get a typed JSON document from the index based
  14. // on its id.
  15. //
  16. // See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/docs-get.html
  17. // for details.
  18. type GetService struct {
  19. client *Client
  20. pretty bool
  21. index string
  22. typ string
  23. id string
  24. routing string
  25. preference string
  26. storedFields []string
  27. refresh string
  28. realtime *bool
  29. fsc *FetchSourceContext
  30. version interface{}
  31. versionType string
  32. parent string
  33. ignoreErrorsOnGeneratedFields *bool
  34. }
  35. // NewGetService creates a new GetService.
  36. func NewGetService(client *Client) *GetService {
  37. return &GetService{
  38. client: client,
  39. typ: "_all",
  40. }
  41. }
  42. // Index is the name of the index.
  43. func (s *GetService) Index(index string) *GetService {
  44. s.index = index
  45. return s
  46. }
  47. // Type is the type of the document (use `_all` to fetch the first document
  48. // matching the ID across all types).
  49. func (s *GetService) Type(typ string) *GetService {
  50. s.typ = typ
  51. return s
  52. }
  53. // Id is the document ID.
  54. func (s *GetService) Id(id string) *GetService {
  55. s.id = id
  56. return s
  57. }
  58. // Parent is the ID of the parent document.
  59. func (s *GetService) Parent(parent string) *GetService {
  60. s.parent = parent
  61. return s
  62. }
  63. // Routing is the specific routing value.
  64. func (s *GetService) Routing(routing string) *GetService {
  65. s.routing = routing
  66. return s
  67. }
  68. // Preference specifies the node or shard the operation should be performed on (default: random).
  69. func (s *GetService) Preference(preference string) *GetService {
  70. s.preference = preference
  71. return s
  72. }
  73. // StoredFields is a list of fields to return in the response.
  74. func (s *GetService) StoredFields(storedFields ...string) *GetService {
  75. s.storedFields = append(s.storedFields, storedFields...)
  76. return s
  77. }
  78. func (s *GetService) FetchSource(fetchSource bool) *GetService {
  79. if s.fsc == nil {
  80. s.fsc = NewFetchSourceContext(fetchSource)
  81. } else {
  82. s.fsc.SetFetchSource(fetchSource)
  83. }
  84. return s
  85. }
  86. func (s *GetService) FetchSourceContext(fetchSourceContext *FetchSourceContext) *GetService {
  87. s.fsc = fetchSourceContext
  88. return s
  89. }
  90. // Refresh the shard containing the document before performing the operation.
  91. func (s *GetService) Refresh(refresh string) *GetService {
  92. s.refresh = refresh
  93. return s
  94. }
  95. // Realtime specifies whether to perform the operation in realtime or search mode.
  96. func (s *GetService) Realtime(realtime bool) *GetService {
  97. s.realtime = &realtime
  98. return s
  99. }
  100. // VersionType is the specific version type.
  101. func (s *GetService) VersionType(versionType string) *GetService {
  102. s.versionType = versionType
  103. return s
  104. }
  105. // Version is an explicit version number for concurrency control.
  106. func (s *GetService) Version(version interface{}) *GetService {
  107. s.version = version
  108. return s
  109. }
  110. // IgnoreErrorsOnGeneratedFields indicates whether to ignore fields that
  111. // are generated if the transaction log is accessed.
  112. func (s *GetService) IgnoreErrorsOnGeneratedFields(ignore bool) *GetService {
  113. s.ignoreErrorsOnGeneratedFields = &ignore
  114. return s
  115. }
  116. // Pretty indicates that the JSON response be indented and human readable.
  117. func (s *GetService) Pretty(pretty bool) *GetService {
  118. s.pretty = pretty
  119. return s
  120. }
  121. // Validate checks if the operation is valid.
  122. func (s *GetService) Validate() error {
  123. var invalid []string
  124. if s.id == "" {
  125. invalid = append(invalid, "Id")
  126. }
  127. if s.index == "" {
  128. invalid = append(invalid, "Index")
  129. }
  130. if s.typ == "" {
  131. invalid = append(invalid, "Type")
  132. }
  133. if len(invalid) > 0 {
  134. return fmt.Errorf("missing required fields: %v", invalid)
  135. }
  136. return nil
  137. }
  138. // buildURL builds the URL for the operation.
  139. func (s *GetService) buildURL() (string, url.Values, error) {
  140. // Build URL
  141. path, err := uritemplates.Expand("/{index}/{type}/{id}", map[string]string{
  142. "id": s.id,
  143. "index": s.index,
  144. "type": s.typ,
  145. })
  146. if err != nil {
  147. return "", url.Values{}, err
  148. }
  149. // Add query string parameters
  150. params := url.Values{}
  151. if s.pretty {
  152. params.Set("pretty", "1")
  153. }
  154. if s.routing != "" {
  155. params.Set("routing", s.routing)
  156. }
  157. if s.parent != "" {
  158. params.Set("parent", s.parent)
  159. }
  160. if s.preference != "" {
  161. params.Set("preference", s.preference)
  162. }
  163. if len(s.storedFields) > 0 {
  164. params.Set("stored_fields", strings.Join(s.storedFields, ","))
  165. }
  166. if s.refresh != "" {
  167. params.Set("refresh", s.refresh)
  168. }
  169. if s.version != nil {
  170. params.Set("version", fmt.Sprintf("%v", s.version))
  171. }
  172. if s.versionType != "" {
  173. params.Set("version_type", s.versionType)
  174. }
  175. if s.realtime != nil {
  176. params.Set("realtime", fmt.Sprintf("%v", *s.realtime))
  177. }
  178. if s.ignoreErrorsOnGeneratedFields != nil {
  179. params.Add("ignore_errors_on_generated_fields", fmt.Sprintf("%v", *s.ignoreErrorsOnGeneratedFields))
  180. }
  181. if s.fsc != nil {
  182. for k, values := range s.fsc.Query() {
  183. params.Add(k, strings.Join(values, ","))
  184. }
  185. }
  186. return path, params, nil
  187. }
  188. // Do executes the operation.
  189. func (s *GetService) Do(ctx context.Context) (*GetResult, error) {
  190. // Check pre-conditions
  191. if err := s.Validate(); err != nil {
  192. return nil, err
  193. }
  194. // Get URL for request
  195. path, params, err := s.buildURL()
  196. if err != nil {
  197. return nil, err
  198. }
  199. // Get HTTP response
  200. res, err := s.client.PerformRequest(ctx, "GET", path, params, nil)
  201. if err != nil {
  202. return nil, err
  203. }
  204. // Return operation response
  205. ret := new(GetResult)
  206. if err := s.client.decoder.Decode(res.Body, ret); err != nil {
  207. return nil, err
  208. }
  209. return ret, nil
  210. }
  211. // -- Result of a get request.
  212. // GetResult is the outcome of GetService.Do.
  213. type GetResult struct {
  214. Index string `json:"_index"` // index meta field
  215. Type string `json:"_type"` // type meta field
  216. Id string `json:"_id"` // id meta field
  217. Uid string `json:"_uid"` // uid meta field (see MapperService.java for all meta fields)
  218. Routing string `json:"_routing"` // routing meta field
  219. Parent string `json:"_parent"` // parent meta field
  220. Version *int64 `json:"_version"` // version number, when Version is set to true in SearchService
  221. Source *json.RawMessage `json:"_source,omitempty"`
  222. Found bool `json:"found,omitempty"`
  223. Fields map[string]interface{} `json:"fields,omitempty"`
  224. //Error string `json:"error,omitempty"` // used only in MultiGet
  225. // TODO double-check that MultiGet now returns details error information
  226. Error *ErrorDetails `json:"error,omitempty"` // only used in MultiGet
  227. }