exists.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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/http"
  9. "net/url"
  10. "gopkg.in/olivere/elastic.v5/uritemplates"
  11. )
  12. // ExistsService checks for the existence of a document using HEAD.
  13. //
  14. // See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/docs-get.html
  15. // for details.
  16. type ExistsService struct {
  17. client *Client
  18. pretty bool
  19. id string
  20. index string
  21. typ string
  22. preference string
  23. realtime *bool
  24. refresh string
  25. routing string
  26. parent string
  27. }
  28. // NewExistsService creates a new ExistsService.
  29. func NewExistsService(client *Client) *ExistsService {
  30. return &ExistsService{
  31. client: client,
  32. }
  33. }
  34. // Id is the document ID.
  35. func (s *ExistsService) Id(id string) *ExistsService {
  36. s.id = id
  37. return s
  38. }
  39. // Index is the name of the index.
  40. func (s *ExistsService) Index(index string) *ExistsService {
  41. s.index = index
  42. return s
  43. }
  44. // Type is the type of the document (use `_all` to fetch the first document
  45. // matching the ID across all types).
  46. func (s *ExistsService) Type(typ string) *ExistsService {
  47. s.typ = typ
  48. return s
  49. }
  50. // Preference specifies the node or shard the operation should be performed on (default: random).
  51. func (s *ExistsService) Preference(preference string) *ExistsService {
  52. s.preference = preference
  53. return s
  54. }
  55. // Realtime specifies whether to perform the operation in realtime or search mode.
  56. func (s *ExistsService) Realtime(realtime bool) *ExistsService {
  57. s.realtime = &realtime
  58. return s
  59. }
  60. // Refresh the shard containing the document before performing the operation.
  61. func (s *ExistsService) Refresh(refresh string) *ExistsService {
  62. s.refresh = refresh
  63. return s
  64. }
  65. // Routing is a specific routing value.
  66. func (s *ExistsService) Routing(routing string) *ExistsService {
  67. s.routing = routing
  68. return s
  69. }
  70. // Parent is the ID of the parent document.
  71. func (s *ExistsService) Parent(parent string) *ExistsService {
  72. s.parent = parent
  73. return s
  74. }
  75. // Pretty indicates that the JSON response be indented and human readable.
  76. func (s *ExistsService) Pretty(pretty bool) *ExistsService {
  77. s.pretty = pretty
  78. return s
  79. }
  80. // buildURL builds the URL for the operation.
  81. func (s *ExistsService) buildURL() (string, url.Values, error) {
  82. // Build URL
  83. path, err := uritemplates.Expand("/{index}/{type}/{id}", map[string]string{
  84. "id": s.id,
  85. "index": s.index,
  86. "type": s.typ,
  87. })
  88. if err != nil {
  89. return "", url.Values{}, err
  90. }
  91. // Add query string parameters
  92. params := url.Values{}
  93. if s.pretty {
  94. params.Set("pretty", "1")
  95. }
  96. if s.realtime != nil {
  97. params.Set("realtime", fmt.Sprintf("%v", *s.realtime))
  98. }
  99. if s.refresh != "" {
  100. params.Set("refresh", s.refresh)
  101. }
  102. if s.routing != "" {
  103. params.Set("routing", s.routing)
  104. }
  105. if s.parent != "" {
  106. params.Set("parent", s.parent)
  107. }
  108. if s.preference != "" {
  109. params.Set("preference", s.preference)
  110. }
  111. return path, params, nil
  112. }
  113. // Validate checks if the operation is valid.
  114. func (s *ExistsService) Validate() error {
  115. var invalid []string
  116. if s.id == "" {
  117. invalid = append(invalid, "Id")
  118. }
  119. if s.index == "" {
  120. invalid = append(invalid, "Index")
  121. }
  122. if s.typ == "" {
  123. invalid = append(invalid, "Type")
  124. }
  125. if len(invalid) > 0 {
  126. return fmt.Errorf("missing required fields: %v", invalid)
  127. }
  128. return nil
  129. }
  130. // Do executes the operation.
  131. func (s *ExistsService) Do(ctx context.Context) (bool, error) {
  132. // Check pre-conditions
  133. if err := s.Validate(); err != nil {
  134. return false, err
  135. }
  136. // Get URL for request
  137. path, params, err := s.buildURL()
  138. if err != nil {
  139. return false, err
  140. }
  141. // Get HTTP response
  142. res, err := s.client.PerformRequest(ctx, "HEAD", path, params, nil, 404)
  143. if err != nil {
  144. return false, err
  145. }
  146. // Return operation response
  147. switch res.StatusCode {
  148. case http.StatusOK:
  149. return true, nil
  150. case http.StatusNotFound:
  151. return false, nil
  152. default:
  153. return false, fmt.Errorf("elastic: got HTTP code %d when it should have been either 200 or 404", res.StatusCode)
  154. }
  155. }