elastomer-client 3.2.3 → 6.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +46 -0
  3. data/.devcontainer/postCreateCommand.sh +4 -0
  4. data/.github/dependabot.yaml +11 -0
  5. data/.github/workflows/main.yml +45 -0
  6. data/.github/workflows/rubocop.yml +15 -0
  7. data/.gitignore +1 -1
  8. data/.rubocop.yml +13 -65
  9. data/.ruby-version +1 -0
  10. data/CHANGELOG.md +76 -0
  11. data/Gemfile +18 -1
  12. data/README.md +110 -51
  13. data/Rakefile +3 -1
  14. data/docker/compose.yaml +71 -0
  15. data/docker/elasticsearch8plus.yml +13 -0
  16. data/docs/README.md +4 -5
  17. data/docs/bulk_indexing.md +1 -1
  18. data/docs/client.md +20 -33
  19. data/docs/cluster.md +8 -8
  20. data/docs/docs.md +5 -5
  21. data/docs/index.md +4 -4
  22. data/docs/multi_search.md +1 -1
  23. data/docs/notifications.md +3 -3
  24. data/docs/scan_scroll.md +1 -1
  25. data/docs/snapshots.md +1 -1
  26. data/docs/templates.md +1 -1
  27. data/elastomer-client.gemspec +7 -16
  28. data/lib/{elastomer → elastomer_client}/client/bulk.rb +70 -47
  29. data/lib/{elastomer → elastomer_client}/client/cluster.rb +18 -16
  30. data/lib/{elastomer → elastomer_client}/client/delete_by_query.rb +6 -4
  31. data/lib/{elastomer → elastomer_client}/client/docs.rb +82 -72
  32. data/lib/{elastomer → elastomer_client}/client/errors.rb +7 -17
  33. data/lib/{elastomer → elastomer_client}/client/index.rb +55 -79
  34. data/lib/{elastomer → elastomer_client}/client/multi_percolate.rb +7 -5
  35. data/lib/{elastomer → elastomer_client}/client/multi_search.rb +5 -3
  36. data/lib/{elastomer → elastomer_client}/client/native_delete_by_query.rb +6 -6
  37. data/lib/{elastomer → elastomer_client}/client/nodes.rb +11 -10
  38. data/lib/{elastomer → elastomer_client}/client/percolator.rb +9 -10
  39. data/lib/elastomer_client/client/reindex.rb +34 -0
  40. data/lib/{elastomer → elastomer_client}/client/repository.rb +7 -5
  41. data/lib/{elastomer → elastomer_client}/client/rest_api_spec/api_spec.rb +7 -6
  42. data/lib/{elastomer → elastomer_client}/client/rest_api_spec/api_spec_v5_6.rb +1 -1
  43. data/lib/elastomer_client/client/rest_api_spec/api_spec_v8_13.rb +7567 -0
  44. data/lib/elastomer_client/client/rest_api_spec/api_spec_v8_7.rb +6553 -0
  45. data/lib/{elastomer → elastomer_client}/client/rest_api_spec/rest_api.rb +5 -3
  46. data/lib/{elastomer → elastomer_client}/client/rest_api_spec.rb +3 -2
  47. data/lib/{elastomer → elastomer_client}/client/scroller.rb +17 -16
  48. data/lib/{elastomer → elastomer_client}/client/snapshot.rb +10 -8
  49. data/lib/{elastomer → elastomer_client}/client/tasks.rb +9 -13
  50. data/lib/{elastomer → elastomer_client}/client/template.rb +10 -9
  51. data/lib/elastomer_client/client/update_by_query.rb +50 -0
  52. data/lib/{elastomer → elastomer_client}/client.rb +51 -62
  53. data/lib/{elastomer → elastomer_client}/core_ext/time.rb +2 -0
  54. data/lib/{elastomer → elastomer_client}/middleware/compress.rb +2 -2
  55. data/lib/{elastomer → elastomer_client}/middleware/encode_json.rb +4 -2
  56. data/lib/{elastomer → elastomer_client}/middleware/limit_size.rb +5 -3
  57. data/lib/{elastomer → elastomer_client}/middleware/opaque_id.rb +10 -7
  58. data/lib/{elastomer → elastomer_client}/middleware/parse_json.rb +5 -3
  59. data/lib/{elastomer → elastomer_client}/notifications.rb +17 -15
  60. data/lib/elastomer_client/version.rb +9 -0
  61. data/lib/elastomer_client/version_support.rb +24 -0
  62. data/script/bootstrap +4 -2
  63. data/script/console +3 -1
  64. data/script/generate-rest-api-spec +77 -22
  65. data/test/assertions.rb +32 -39
  66. data/test/client/bulk_test.rb +166 -141
  67. data/test/client/cluster_test.rb +35 -13
  68. data/test/client/docs_test.rb +387 -274
  69. data/test/client/errors_test.rb +38 -40
  70. data/test/client/index_test.rb +243 -202
  71. data/test/client/multi_percolate_test.rb +46 -41
  72. data/test/client/multi_search_test.rb +122 -67
  73. data/test/client/native_delete_by_query_test.rb +96 -88
  74. data/test/client/nodes_test.rb +21 -10
  75. data/test/client/percolator_test.rb +19 -14
  76. data/test/client/reindex_test.rb +100 -0
  77. data/test/client/repository_test.rb +31 -19
  78. data/test/client/rest_api_spec/api_spec_test.rb +13 -11
  79. data/test/client/rest_api_spec/rest_api_test.rb +9 -7
  80. data/test/client/scroller_test.rb +44 -70
  81. data/test/client/snapshot_test.rb +38 -21
  82. data/test/client/stubbed_client_test.rb +7 -4
  83. data/test/client/tasks_test.rb +12 -17
  84. data/test/client/template_test.rb +34 -13
  85. data/test/client/update_by_query_test.rb +137 -0
  86. data/test/client_test.rb +158 -92
  87. data/test/core_ext/time_test.rb +14 -12
  88. data/test/middleware/encode_json_test.rb +18 -7
  89. data/test/middleware/opaque_id_test.rb +18 -14
  90. data/test/middleware/parse_json_test.rb +17 -9
  91. data/test/mock_response.rb +30 -0
  92. data/test/notifications_test.rb +15 -8
  93. data/test/test_helper.rb +40 -97
  94. data/test/version_support_test.rb +13 -78
  95. metadata +60 -208
  96. data/.overcommit.yml +0 -5
  97. data/.travis.yml +0 -34
  98. data/docker/docker-compose.cibuild.yml +0 -8
  99. data/docker/docker-compose.es24.yml +0 -34
  100. data/docker/docker-compose.es56.yml +0 -37
  101. data/docs/warmers.md +0 -3
  102. data/lib/elastomer/client/app_delete_by_query.rb +0 -144
  103. data/lib/elastomer/client/rest_api_spec/api_spec_v2_3.rb +0 -2232
  104. data/lib/elastomer/client/rest_api_spec/api_spec_v2_4.rb +0 -2250
  105. data/lib/elastomer/client/warmer.rb +0 -98
  106. data/lib/elastomer/version.rb +0 -7
  107. data/lib/elastomer/version_support.rb +0 -182
  108. data/script/cibuild +0 -103
  109. data/script/cibuild-elastomer-client +0 -1
  110. data/script/cibuild-elastomer-client-es24 +0 -8
  111. data/script/cibuild-elastomer-client-es56 +0 -8
  112. data/test/client/app_delete_by_query_test.rb +0 -192
  113. data/test/client/es_5_x_warmer_test.rb +0 -13
  114. data/test/client/warmer_test.rb +0 -60
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../test_helper"
2
4
 
3
- describe Elastomer::Client::Snapshot do
5
+ describe ElastomerClient::Client::Snapshot do
4
6
  before do
5
7
  @index = nil
6
8
  @restored_index = nil
@@ -12,6 +14,9 @@ describe Elastomer::Client::Snapshot do
12
14
  @index_name = "elastomer-snapshot-test-index"
13
15
  @index = $client.index(@index_name)
14
16
  @name = "elastomer-test"
17
+ if $client.version_support.es_version_8_plus?
18
+ $client.cluster.update_settings persistent: { "ingest.geoip.downloader.enabled" => "false" }
19
+ end
15
20
  end
16
21
 
17
22
  after do
@@ -21,24 +26,28 @@ describe Elastomer::Client::Snapshot do
21
26
  it "determines if a snapshot exists" do
22
27
  with_tmp_repo do |repo|
23
28
  snapshot = repo.snapshot(@name)
24
- assert_equal false, snapshot.exists?
25
- assert_equal false, snapshot.exist?
26
- snapshot.create({}, :wait_for_completion => true)
27
- assert_equal true, snapshot.exist?
29
+
30
+ refute_predicate snapshot, :exists?
31
+ refute_predicate snapshot, :exist?
32
+ snapshot.create({}, wait_for_completion: true)
33
+
34
+ assert_predicate snapshot, :exist?
28
35
  end
29
36
  end
30
37
 
31
38
  it "creates snapshots" do
32
39
  with_tmp_repo do |repo|
33
- response = repo.snapshot(@name).create({}, :wait_for_completion => true)
40
+ response = repo.snapshot(@name).create({}, wait_for_completion: true)
41
+
34
42
  assert_equal @name, response["snapshot"]["snapshot"]
35
43
  end
36
44
  end
37
45
 
38
46
  it "creates snapshots with options" do
39
- @index.create(:number_of_shards => 1, :number_of_replicas => 0)
47
+ @index.create(settings: { number_of_shards: 1, number_of_replicas: 0 })
40
48
  with_tmp_repo do |repo|
41
- response = repo.snapshot(@name).create({:indices => [@index_name]}, :wait_for_completion => true)
49
+ response = repo.snapshot(@name).create({ indices: [@index_name] }, wait_for_completion: true)
50
+
42
51
  assert_equal [@index_name], response["snapshot"]["indices"]
43
52
  assert_equal 1, response["snapshot"]["shards"]["total"]
44
53
  end
@@ -47,17 +56,20 @@ describe Elastomer::Client::Snapshot do
47
56
  it "gets snapshot info for one and all" do
48
57
  with_tmp_snapshot do |snapshot, repo|
49
58
  response = snapshot.get
59
+
50
60
  assert_equal snapshot.name, response["snapshots"][0]["snapshot"]
51
61
  response = repo.snapshots.get
62
+
52
63
  assert_equal snapshot.name, response["snapshots"][0]["snapshot"]
53
64
  end
54
65
  end
55
66
 
56
67
  it "gets snapshot status for one and all" do
57
- @index.create(:number_of_shards => 1, :number_of_replicas => 0)
68
+ @index.create(settings: { number_of_shards: 1, number_of_replicas: 0 })
58
69
  with_tmp_repo do |repo|
59
- repo.snapshot(@name).create({:indices => [@index_name]}, :wait_for_completion => true)
70
+ repo.snapshot(@name).create({indices: [@index_name]}, wait_for_completion: true)
60
71
  response = repo.snapshot(@name).status
72
+
61
73
  assert_equal 1, response["snapshots"][0]["shards_stats"]["total"]
62
74
  end
63
75
  end
@@ -67,9 +79,11 @@ describe Elastomer::Client::Snapshot do
67
79
  # check for an empty result instead
68
80
  with_tmp_repo do |repo|
69
81
  response = repo.snapshots.status
70
- assert_equal [], response["snapshots"]
82
+
83
+ assert_empty response["snapshots"]
71
84
  response = $client.snapshot.status
72
- assert_equal [], response["snapshots"]
85
+
86
+ assert_empty response["snapshots"]
73
87
  end
74
88
  end
75
89
 
@@ -81,18 +95,20 @@ describe Elastomer::Client::Snapshot do
81
95
  it "deletes snapshots" do
82
96
  with_tmp_snapshot do |snapshot|
83
97
  response = snapshot.delete
84
- assert_equal true, response["acknowledged"]
98
+
99
+ assert response["acknowledged"]
85
100
  end
86
101
  end
87
102
 
88
103
  it "restores snapshots" do
89
- @index.create(:number_of_shards => 1, :number_of_replicas => 0)
104
+ @index.create(settings: { number_of_shards: 1, number_of_replicas: 0 })
90
105
  wait_for_index(@index_name)
91
106
  with_tmp_repo do |repo|
92
107
  snapshot = repo.snapshot(@name)
93
- snapshot.create({:indices => [@index_name]}, :wait_for_completion => true)
108
+ snapshot.create({ indices: [@index_name] }, wait_for_completion: true)
94
109
  @index.delete
95
- response = snapshot.restore({}, :wait_for_completion => true)
110
+ response = snapshot.restore({}, wait_for_completion: true)
111
+
96
112
  assert_equal 1, response["snapshot"]["shards"]["total"]
97
113
  end
98
114
  end
@@ -108,15 +124,16 @@ describe Elastomer::Client::Snapshot do
108
124
  end
109
125
 
110
126
  it "restores snapshots with options" do
111
- @index.create(:number_of_shards => 1, :number_of_replicas => 0)
127
+ @index.create(settings: { number_of_shards: 1, number_of_replicas: 0 })
112
128
  wait_for_index(@index_name)
113
129
  with_tmp_repo do |repo|
114
130
  snapshot = repo.snapshot(@name)
115
- snapshot.create({:indices => [@index_name]}, :wait_for_completion => true)
131
+ snapshot.create({indices: [@index_name]}, wait_for_completion: true)
116
132
  response = snapshot.restore({
117
- :rename_pattern => @index_name,
118
- :rename_replacement => @restored_index_name
119
- }, :wait_for_completion => true)
133
+ rename_pattern: @index_name,
134
+ rename_replacement: @restored_index_name
135
+ }, wait_for_completion: true)
136
+
120
137
  assert_equal [@restored_index_name], response["snapshot"]["indices"]
121
138
  assert_equal 1, response["snapshot"]["shards"]["total"]
122
139
  end
@@ -1,21 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../test_helper"
2
4
 
3
5
  describe "stubbed client tests" do
4
6
  before do
5
7
  @stubs = Faraday::Adapter.lookup_middleware(:test)::Stubs.new
6
- @client = Elastomer::Client.new :adapter => [:test, @stubs]
8
+ @client = ElastomerClient::Client.new adapter: [:test, @stubs]
7
9
  @client.instance_variable_set(:@version, "5.6.4")
8
10
  end
9
11
 
10
- describe Elastomer::Client::Cluster do
12
+ describe ElastomerClient::Client::Cluster do
11
13
  it "reroutes shards" do
12
14
  @stubs.post "/_cluster/reroute?dry_run=true" do |env|
13
15
  assert_match %r/^\{"commands":\[\{"move":\{[^\{\}]+\}\}\]\}$/, env[:body]
14
16
  [200, {"Content-Type" => "application/json"}, '{"acknowledged" : true}']
15
17
  end
16
18
 
17
- commands = { :move => { :index => "test", :shard => 0, :from_node => "node1", :to_node => "node2" }}
18
- h = @client.cluster.reroute commands, :dry_run => true
19
+ commands = { move: { index: "test", shard: 0, from_node: "node1", to_node: "node2" }}
20
+ h = @client.cluster.reroute commands, dry_run: true
21
+
19
22
  assert_acknowledged h
20
23
  end
21
24
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../test_helper"
2
4
 
3
- describe Elastomer::Client::Tasks do
5
+ describe ElastomerClient::Client::Tasks do
4
6
  before do
5
7
  @tasks = $client.tasks
6
8
 
@@ -15,20 +17,19 @@ describe Elastomer::Client::Tasks do
15
17
 
16
18
  it "list all in-flight tasks" do
17
19
  h = @tasks.get
18
- assert h["nodes"].keys.size > 0
20
+
21
+ assert_operator h["nodes"].keys.size, :>, 0
19
22
 
20
23
  total_tasks = h["nodes"].map { |k, v| v["tasks"].keys.count }.sum
21
- assert total_tasks > 0
24
+
25
+ assert_operator total_tasks, :>, 0
22
26
  end
23
27
 
24
28
  it "groups by parent->child relationships when get-all tasks API is grouped by 'parents'" do
25
- unless $client.version_support.es_version_5_x?
26
- skip "Tasks API is not supported in ES version #{$client.version}"
27
- end
28
-
29
- h = @tasks.get :group_by => "parents"
29
+ h = @tasks.get group_by: "parents"
30
30
  parent_id = h["tasks"].select { |k, v| v.key?("children") }.keys.first
31
31
  childs_parent_ref = h.dig("tasks", parent_id, "children").first["parent_task_id"]
32
+
32
33
  assert_equal parent_id, childs_parent_ref
33
34
  end
34
35
 
@@ -47,7 +48,7 @@ describe Elastomer::Client::Tasks do
47
48
 
48
49
  it "raises exception when get_by_id is called w/invalid node ID is supplied" do
49
50
  assert_raises(ArgumentError) do
50
- @tasks.get_by_id nil, 42
51
+ @tasks.get_by_id nil, 42
51
52
  end
52
53
  end
53
54
 
@@ -64,7 +65,7 @@ describe Elastomer::Client::Tasks do
64
65
  begin
65
66
  resp = @tasks.wait_by_id t["node"], t["id"], "3s"
66
67
  success = !resp.key?("node_failures")
67
- rescue Elastomer::Client::ServerError => e
68
+ rescue ElastomerClient::Client::ServerError => e
68
69
  # this means the timeout expired before the task finished, but it's a good thing!
69
70
  success = /Timed out waiting for completion/ =~ e.message
70
71
  end
@@ -90,13 +91,7 @@ describe Elastomer::Client::Tasks do
90
91
  t = ts.values.first
91
92
  resp = @tasks.get_by_id t["node"], t["id"]
92
93
 
93
- # ES 5.x and 2.x responses are structured differently
94
- if $client.version_support.tasks_new_response_format?
95
- found_by_id = resp["task"]["node"] == t["node"] && resp["task"]["id"] == t["id"]
96
- else
97
- nid, tid = resp["nodes"][t["node"]]["tasks"].keys.first.split(":")
98
- found_by_id = nid == t["node"] && tid.to_i == t["id"]
99
- end
94
+ found_by_id = resp["task"]["node"] == t["node"] && resp["task"]["id"] == t["id"]
100
95
 
101
96
  break if found_by_id
102
97
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "../test_helper"
2
4
 
3
- describe Elastomer::Client::Cluster do
5
+ describe ElastomerClient::Client::Cluster do
4
6
 
5
7
  before do
6
8
  @name = "elastomer-template-test"
@@ -12,27 +14,46 @@ describe Elastomer::Client::Cluster do
12
14
  end
13
15
 
14
16
  it "lists templates in the cluster" do
15
- @template.create({:template => "test-elastomer*"})
17
+ if $client.version_support.es_version_8_plus?
18
+ @template.create({index_patterns: ["test-elastomer*"]})
19
+ else
20
+ @template.create({template: "test-elastomer*"})
21
+ end
16
22
  templates = $client.cluster.templates
17
- assert !templates.empty?, "expected to see a template"
23
+
24
+ refute_empty templates, "expected to see a template"
18
25
  end
19
26
 
20
27
  it "creates a template" do
21
- assert !@template.exists?, "the template should not exist"
22
-
23
- @template.create({
24
- :template => "test-elastomer*",
25
- :settings => { :number_of_shards => 3 },
26
- :mappings => {
27
- :doco => { :_source => { :enabled => false }}
28
- }
28
+ refute_predicate @template, :exists?, "the template should not exist"
29
+
30
+ if $client.version_support.es_version_8_plus?
31
+ template_config = {index_patterns: ["test-elastomer*"]}
32
+ else
33
+ template_config = {template: "test-elastomer*"}
34
+ end
35
+
36
+ template_config.merge!({
37
+ settings: { number_of_shards: 3 },
38
+ mappings: mappings_wrapper("book", {
39
+ _source: { enabled: false }
40
+ })
29
41
  })
30
42
 
31
- assert @template.exists?, " we now have a cluster-test template"
43
+ @template.create(template_config)
44
+
45
+ assert_predicate @template, :exists?, " we now have a cluster-test template"
32
46
 
33
47
  template = @template.get
48
+
34
49
  assert_equal [@name], template.keys
35
- assert_equal "test-elastomer*", template[@name]["template"]
50
+
51
+ if $client.version_support.es_version_8_plus?
52
+ assert_equal "test-elastomer*", template[@name]["index_patterns"][0]
53
+ else
54
+ assert_equal "test-elastomer*", template[@name]["template"]
55
+ end
56
+
36
57
  assert_equal "3", template[@name]["settings"]["index"]["number_of_shards"]
37
58
  end
38
59
  end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../test_helper"
4
+
5
+ describe ElastomerClient::Client::UpdateByQuery do
6
+ before do
7
+ @index = $client.index "elastomer-update-by-query-test"
8
+ @index.delete if @index.exists?
9
+ @docs = @index.docs("docs")
10
+ end
11
+
12
+ after do
13
+ @index.delete if @index.exists?
14
+ end
15
+
16
+ describe "when an index with documents exists" do
17
+ before do
18
+ @index.create(nil)
19
+ wait_for_index(@index.name)
20
+ end
21
+
22
+ it "updates by query" do
23
+ @docs.index({ _id: 0, name: "mittens" })
24
+ @docs.index({ _id: 1, name: "luna" })
25
+
26
+ @index.refresh
27
+
28
+ query = {
29
+ query: {
30
+ match: {
31
+ name: "mittens"
32
+ }
33
+ },
34
+ script: {
35
+ source: "ctx._source.name = 'mittens updated'"
36
+ }
37
+ }
38
+
39
+ response = @index.update_by_query(query)
40
+
41
+ refute_nil response["took"]
42
+ refute(response["timed_out"])
43
+ assert_equal(1, response["batches"])
44
+ assert_equal(1, response["total"])
45
+ assert_equal(1, response["updated"])
46
+ assert_empty(response["failures"])
47
+
48
+ @index.refresh
49
+ response = @docs.multi_get(ids: [0, 1])
50
+
51
+ assert_equal "mittens updated", response.fetch("docs")[0]["_source"]["name"]
52
+ assert_equal "luna", response.fetch("docs")[1]["_source"]["name"]
53
+ end
54
+
55
+ it "fails when internal version is 0" do
56
+ if $client.version_support.es_version_8_plus?
57
+ skip "Concurrency control with internal version is not supported in ES #{$client.version}"
58
+ end
59
+ @docs.index({_id: 0, name: "mittens"})
60
+ # Creating a document with external version 0 also sets the internal version to 0
61
+ # Otherwise you can't index a document with version 0.
62
+ @docs.index({_id: 1, _version: 0, _version_type: "external", name: "mittens"})
63
+ @index.refresh
64
+
65
+ query = {
66
+ query: {
67
+ match: {
68
+ name: "mittens"
69
+ }
70
+ }
71
+ }
72
+
73
+ assert_raises(ElastomerClient::Client::RequestError) do
74
+ @index.update_by_query(query)
75
+ end
76
+ end
77
+
78
+ it "fails when an unknown parameter is provided" do
79
+ assert_raises(ElastomerClient::Client::IllegalArgument) do
80
+ @index.update_by_query({}, foo: "bar")
81
+ end
82
+ end
83
+
84
+ it "updates by query when routing is specified" do
85
+ index = $client.index "elastomer-update-by-query-routing-test"
86
+ index.delete if index.exists?
87
+ type = "docs"
88
+ # default number of shards in ES8 is 1, so set it to 2 shards so routing to different shards can be tested
89
+ settings = $client.version_support.es_version_8_plus? ? { number_of_shards: 2 } : {}
90
+ index.create({
91
+ settings:,
92
+ mappings: mappings_wrapper(type, {
93
+ properties: {
94
+ name: { type: "text", analyzer: "standard" },
95
+ },
96
+ _routing: { required: true }
97
+ })
98
+ })
99
+ wait_for_index(@index.name)
100
+ docs = index.docs(type)
101
+
102
+ docs.index({ _id: 0, _routing: "cat", name: "mittens" })
103
+ docs.index({ _id: 1, _routing: "cat", name: "luna" })
104
+ docs.index({ _id: 2, _routing: "dog", name: "mittens" })
105
+
106
+ query = {
107
+ query: {
108
+ match: {
109
+ name: "mittens"
110
+ }
111
+ },
112
+ script: {
113
+ source: "ctx._source.name = 'mittens updated'"
114
+ }
115
+ }
116
+
117
+ index.refresh
118
+ response = index.update_by_query(query, routing: "cat")
119
+
120
+ assert_equal(1, response["updated"])
121
+
122
+ response = docs.multi_get({
123
+ docs: [
124
+ { _id: 0, routing: "cat" },
125
+ { _id: 1, routing: "cat" },
126
+ { _id: 2, routing: "dog" },
127
+ ]
128
+ })
129
+
130
+ assert_equal "mittens updated", response.fetch("docs")[0]["_source"]["name"]
131
+ assert_equal "luna", response.fetch("docs")[1]["_source"]["name"]
132
+ assert_equal "mittens", response.fetch("docs")[2]["_source"]["name"]
133
+
134
+ index.delete if index.exists?
135
+ end
136
+ end
137
+ end