update.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. // UpdateResult is the result of updating a document in Elasticsearch.
  13. type UpdateResult struct {
  14. Index string `json:"_index"`
  15. Type string `json:"_type"`
  16. Id string `json:"_id"`
  17. Version int `json:"_version"`
  18. Created bool `json:"created"`
  19. GetResult *GetResult `json:"get"`
  20. }
  21. // UpdateService updates a document in Elasticsearch.
  22. // See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-update.html
  23. // for details.
  24. type UpdateService struct {
  25. client *Client
  26. index string
  27. typ string
  28. id string
  29. routing string
  30. parent string
  31. script string
  32. scriptId string
  33. scriptFile string
  34. scriptType string
  35. scriptLang string
  36. scriptParams map[string]interface{}
  37. fields []string
  38. version *int64
  39. versionType string
  40. retryOnConflict *int
  41. refresh *bool
  42. replicationType string
  43. consistencyLevel string
  44. upsert interface{}
  45. scriptedUpsert *bool
  46. docAsUpsert *bool
  47. detectNoop *bool
  48. doc interface{}
  49. timeout string
  50. pretty bool
  51. }
  52. // NewUpdateService creates the service to update documents in Elasticsearch.
  53. func NewUpdateService(client *Client) *UpdateService {
  54. builder := &UpdateService{
  55. client: client,
  56. scriptParams: make(map[string]interface{}),
  57. fields: make([]string, 0),
  58. }
  59. return builder
  60. }
  61. // Index is the name of the Elasticsearch index (required).
  62. func (b *UpdateService) Index(name string) *UpdateService {
  63. b.index = name
  64. return b
  65. }
  66. // Type is the type of the document (required).
  67. func (b *UpdateService) Type(typ string) *UpdateService {
  68. b.typ = typ
  69. return b
  70. }
  71. // Id is the identifier of the document to update (required).
  72. func (b *UpdateService) Id(id string) *UpdateService {
  73. b.id = id
  74. return b
  75. }
  76. // Routing specifies a specific routing value.
  77. func (b *UpdateService) Routing(routing string) *UpdateService {
  78. b.routing = routing
  79. return b
  80. }
  81. // Parent sets the id of the parent document.
  82. func (b *UpdateService) Parent(parent string) *UpdateService {
  83. b.parent = parent
  84. return b
  85. }
  86. // Script is the URL-encoded script definition.
  87. func (b *UpdateService) Script(script string) *UpdateService {
  88. b.script = script
  89. return b
  90. }
  91. // ScriptId is the id of a stored script.
  92. func (b *UpdateService) ScriptId(scriptId string) *UpdateService {
  93. b.scriptId = scriptId
  94. return b
  95. }
  96. // ScriptFile is the file name of a stored script.
  97. // See https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html for details.
  98. func (b *UpdateService) ScriptFile(scriptFile string) *UpdateService {
  99. b.scriptFile = scriptFile
  100. return b
  101. }
  102. func (b *UpdateService) ScriptType(scriptType string) *UpdateService {
  103. b.scriptType = scriptType
  104. return b
  105. }
  106. // ScriptLang defines the scripting language (default: groovy).
  107. func (b *UpdateService) ScriptLang(scriptLang string) *UpdateService {
  108. b.scriptLang = scriptLang
  109. return b
  110. }
  111. func (b *UpdateService) ScriptParams(params map[string]interface{}) *UpdateService {
  112. b.scriptParams = params
  113. return b
  114. }
  115. // RetryOnConflict specifies how many times the operation should be retried
  116. // when a conflict occurs (default: 0).
  117. func (b *UpdateService) RetryOnConflict(retryOnConflict int) *UpdateService {
  118. b.retryOnConflict = &retryOnConflict
  119. return b
  120. }
  121. // Fields is a list of fields to return in the response.
  122. func (b *UpdateService) Fields(fields ...string) *UpdateService {
  123. b.fields = make([]string, 0, len(fields))
  124. b.fields = append(b.fields, fields...)
  125. return b
  126. }
  127. // Version defines the explicit version number for concurrency control.
  128. func (b *UpdateService) Version(version int64) *UpdateService {
  129. b.version = &version
  130. return b
  131. }
  132. // VersionType is one of "internal" or "force".
  133. func (b *UpdateService) VersionType(versionType string) *UpdateService {
  134. b.versionType = versionType
  135. return b
  136. }
  137. // Refresh the index after performing the update.
  138. func (b *UpdateService) Refresh(refresh bool) *UpdateService {
  139. b.refresh = &refresh
  140. return b
  141. }
  142. // ReplicationType is one of "sync" or "async".
  143. func (b *UpdateService) ReplicationType(replicationType string) *UpdateService {
  144. b.replicationType = replicationType
  145. return b
  146. }
  147. // ConsistencyLevel is one of "one", "quorum", or "all".
  148. // It sets the write consistency setting for the update operation.
  149. func (b *UpdateService) ConsistencyLevel(consistencyLevel string) *UpdateService {
  150. b.consistencyLevel = consistencyLevel
  151. return b
  152. }
  153. // Doc allows for updating a partial document.
  154. func (b *UpdateService) Doc(doc interface{}) *UpdateService {
  155. b.doc = doc
  156. return b
  157. }
  158. // Upsert can be used to index the document when it doesn't exist yet.
  159. // Use this e.g. to initialize a document with a default value.
  160. func (b *UpdateService) Upsert(doc interface{}) *UpdateService {
  161. b.upsert = doc
  162. return b
  163. }
  164. // DocAsUpsert can be used to insert the document if it doesn't already exist.
  165. func (b *UpdateService) DocAsUpsert(docAsUpsert bool) *UpdateService {
  166. b.docAsUpsert = &docAsUpsert
  167. return b
  168. }
  169. // DetectNoop will instruct Elasticsearch to check if changes will occur
  170. // when updating via Doc. It there aren't any changes, the request will
  171. // turn into a no-op.
  172. func (b *UpdateService) DetectNoop(detectNoop bool) *UpdateService {
  173. b.detectNoop = &detectNoop
  174. return b
  175. }
  176. // ScriptedUpsert should be set to true if the referenced script
  177. // (defined in Script or ScriptId) should be called to perform an insert.
  178. // The default is false.
  179. func (b *UpdateService) ScriptedUpsert(scriptedUpsert bool) *UpdateService {
  180. b.scriptedUpsert = &scriptedUpsert
  181. return b
  182. }
  183. // Timeout is an explicit timeout for the operation, e.g. "1000", "1s" or "500ms".
  184. func (b *UpdateService) Timeout(timeout string) *UpdateService {
  185. b.timeout = timeout
  186. return b
  187. }
  188. // Pretty instructs to return human readable, prettified JSON.
  189. func (b *UpdateService) Pretty(pretty bool) *UpdateService {
  190. b.pretty = pretty
  191. return b
  192. }
  193. // url returns the URL part of the document request.
  194. func (b *UpdateService) url() (string, url.Values, error) {
  195. // Build url
  196. path := "/{index}/{type}/{id}/_update"
  197. path, err := uritemplates.Expand(path, map[string]string{
  198. "index": b.index,
  199. "type": b.typ,
  200. "id": b.id,
  201. })
  202. if err != nil {
  203. return "", url.Values{}, err
  204. }
  205. // Parameters
  206. params := make(url.Values)
  207. if b.pretty {
  208. params.Set("pretty", "true")
  209. }
  210. if b.routing != "" {
  211. params.Set("routing", b.routing)
  212. }
  213. if b.parent != "" {
  214. params.Set("parent", b.parent)
  215. }
  216. if b.timeout != "" {
  217. params.Set("timeout", b.timeout)
  218. }
  219. if b.refresh != nil {
  220. params.Set("refresh", fmt.Sprintf("%v", *b.refresh))
  221. }
  222. if b.replicationType != "" {
  223. params.Set("replication", b.replicationType)
  224. }
  225. if b.consistencyLevel != "" {
  226. params.Set("consistency", b.consistencyLevel)
  227. }
  228. if len(b.fields) > 0 {
  229. params.Set("fields", strings.Join(b.fields, ","))
  230. }
  231. if b.version != nil {
  232. params.Set("version", fmt.Sprintf("%d", *b.version))
  233. }
  234. if b.versionType != "" {
  235. params.Set("version_type", b.versionType)
  236. }
  237. if b.retryOnConflict != nil {
  238. params.Set("retry_on_conflict", fmt.Sprintf("%v", *b.retryOnConflict))
  239. }
  240. return path, params, nil
  241. }
  242. // body returns the body part of the document request.
  243. func (b *UpdateService) body() (interface{}, error) {
  244. source := make(map[string]interface{})
  245. if b.script != "" {
  246. source["script"] = b.script
  247. }
  248. if b.scriptId != "" {
  249. source["script_id"] = b.scriptId
  250. }
  251. if b.scriptFile != "" {
  252. source["script_file"] = b.scriptFile
  253. }
  254. if b.scriptLang != "" {
  255. source["lang"] = b.scriptLang
  256. }
  257. if len(b.scriptParams) > 0 {
  258. source["params"] = b.scriptParams
  259. }
  260. if b.scriptedUpsert != nil {
  261. source["scripted_upsert"] = *b.scriptedUpsert
  262. }
  263. if b.upsert != nil {
  264. source["upsert"] = b.upsert
  265. }
  266. if b.doc != nil {
  267. source["doc"] = b.doc
  268. }
  269. if b.docAsUpsert != nil {
  270. source["doc_as_upsert"] = *b.docAsUpsert
  271. }
  272. if b.detectNoop != nil {
  273. source["detect_noop"] = *b.detectNoop
  274. }
  275. return source, nil
  276. }
  277. // Do executes the update operation.
  278. func (b *UpdateService) Do() (*UpdateResult, error) {
  279. path, params, err := b.url()
  280. if err != nil {
  281. return nil, err
  282. }
  283. // Get body of the request
  284. body, err := b.body()
  285. if err != nil {
  286. return nil, err
  287. }
  288. // Get response
  289. res, err := b.client.PerformRequest("POST", path, params, body)
  290. if err != nil {
  291. return nil, err
  292. }
  293. // Return result
  294. ret := new(UpdateResult)
  295. if err := json.Unmarshal(res.Body, ret); err != nil {
  296. return nil, err
  297. }
  298. return ret, nil
  299. }