Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ Please mark backwards incompatible changes with an exclamation mark at the start

## [Unreleased]

### Added
- The `#update` method to `JayAPI::Elasticsearch::Client`.

### Deprecated
- The `Elasticsearch::QueryBuilder::Script` class is now deprecated, please
use `Elasticsearch::Script` instead.

## [29.7.0] - 2026-04-28

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ The code above would produce the following query:

These scripts **must** be simple strings, they do not follow the pattern of
other scripted elements in Elasticsearch's DSL. Do not use
``QueryBuilder::Script`` objects here. Their use will produce unintended
``Elasticsearch::Script`` objects here. Their use will produce unintended
results.

composite
Expand Down Expand Up @@ -396,7 +396,7 @@ Code example:
aggs.sum('total_sales', field: 'price')
aggs.bucket_selector(
'sales_bucket_filter', buckets_path: { totalSales: 'total_sales' },
script: JayAPI::Elasticsearch::QueryBuilder::Script.new(source: 'params.totalSales > 200')
script: JayAPI::Elasticsearch::Script.new(source: 'params.totalSales > 200')
)
end

Expand Down
1 change: 1 addition & 0 deletions lib/jay_api/elasticsearch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
require_relative 'elasticsearch/query_builder'
require_relative 'elasticsearch/query_results'
require_relative 'elasticsearch/response'
require_relative 'elasticsearch/script'
require_relative 'elasticsearch/search_after_results'
require_relative 'elasticsearch/stats'
require_relative 'elasticsearch/tasks'
Expand Down
8 changes: 8 additions & 0 deletions lib/jay_api/elasticsearch/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ def tasks
def cluster
@cluster ||= ::JayAPI::Elasticsearch::Cluster.new(transport_client)
end

# Calls the +Elasticsearch::Client+'s #update method forwarding the given
# parameters. If the request fails, additional retries will be performed.
# @see Elasticsearch::API::Actions#update for more info about the
# arguments and the return value.
def update(**args)
retry_request { transport_client.update(**args) }
end
end
end
end
43 changes: 43 additions & 0 deletions lib/jay_api/elasticsearch/index.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# frozen_string_literal: true

require 'active_support'
require 'active_support/core_ext/object/blank'

require_relative 'indexable'
require_relative 'indices/settings'
require_relative 'errors/writable_index_error'
Expand Down Expand Up @@ -52,6 +55,46 @@ def index(data, type: DEFAULT_DOC_TYPE)
super.first
end

# Updates a document by ID.
# @param [String] id The ID of the document to update.
# @param [Hash, nil] doc The partial document to update the existing
# document with. If +nil+ is given, the +script+ parameter must be
# provided. If both +doc+ and +script+ are given, the +doc+ parameter
# will be ignored by Elasticsearch.
# @param [JayAPI::Elasticsearch::Script, Hash, nil] script The script to
# update the existing document with. If +nil+ is given, the +doc+
# parameter must be provided. It's recommended to use a
# +JayAPI::Elasticsearch::Script+ object, but a Hash can also be used.
# @return [Hash] A Hash containing information about the updated document.
# An example of such Hash is:
#
# {
# "_index" : "xyz01_build_properties",
# "_type" : "_doc",
# "_id" : "ns4AAZ8BXEjZhYMmw-8y",
# "_version" : 7,
# "result" : "updated",
# "_shards" : {
# "total" : 2,
# "successful" : 2,
# "failed" : 0
# },
# "_seq_no" : 11,
# "_primary_term" : 1
# }
#
# For information on how to use the script and about the contents of the
# returned Hash please see:
# https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-update
# @raise [ArgumentError] If both +doc+ and +script+ are +nil+.
# @raise [Elasticsearch::Transport::Transport::ServerError] If the
# update fails.
def update(id:, doc: nil, script: nil)
raise ArgumentError, "Either 'doc' or 'script' must be provided" if doc.blank? && script.blank?

client.update(index: index_name, id:, body: { doc: doc, script: script&.to_h }.compact)
end

# @return [JayAPI::Elasticsearch::Indices::Settings] The settings for the
# index.
def settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class BucketSelector < ::JayAPI::Elasticsearch::QueryBuilder::Aggregations::Aggr
# The keys are the names of the script variables, the values the
# paths to the metrics (relative to the parent aggregation).
# The script will receive these variables in its +params+.
# @param [JayAPI::Elasticsearch::QueryBuilder::Script] script
# Script used to decide whether to keep each bucket.
# @param [JayAPI::Elasticsearch::Script] script Script used to decide
# whether to keep each bucket.
# @param [String, nil] gap_policy Optional gap policy (e.g. "skip",
# "insert_zeros").
def initialize(name, buckets_path:, script:, gap_policy: nil)
Expand Down
7 changes: 3 additions & 4 deletions lib/jay_api/elasticsearch/query_builder/aggregations/terms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ class Terms < ::JayAPI::Elasticsearch::QueryBuilder::Aggregations::Aggregation
# @param [String] name The name used by Elasticsearch to identify each
# of the aggregations.
# @param [String] field The field whose unique values should be counted.
# @param [JayAPI::Elasticsearch::QueryBuilder::Script] script If a
# script is given the aggregation will count the unique values
# returned by the script instead of the unique values in a specific
# field.
# @param [JayAPI::Elasticsearch::Script] script If a script is given
# the aggregation will count the unique values returned by the
# script instead of the unique values in a specific field.
# @param [Integer] size By default the aggregation returns the top 10
# unique values (the ones with the higher frequency). By specifying
# a size this can be changed.
Expand Down
29 changes: 4 additions & 25 deletions lib/jay_api/elasticsearch/query_builder/script.rb
Original file line number Diff line number Diff line change
@@ -1,36 +1,15 @@
# frozen_string_literal: true

require_relative '../script'

module JayAPI
module Elasticsearch
class QueryBuilder
# Represents a scripted element in a query. This scripted element can be
# used in different places. It can be used in a query clause, but can
# also be used to create custom aggregations.
class Script
attr_reader :source, :lang, :params

# @param [String] source The source for the script element.
# @param [String] lang The language the script is written in.
# @param [Hash] params A +Hash+ with key-value pairs for the script's
# parameters.
def initialize(source:, lang: 'painless', params: nil)
@source = source
@lang = lang

# Keeps the parameters from being modified from the outside after the
# class has been initialized.
@params = params.dup.freeze
end

# @return [Hash] The hash representation of the scripted element.
def to_h
{
source: source,
lang: lang,
params: params
}.compact
end
end
# @deprecated Use +JayAPI::Elasticsearch::Script+ instead.
Script = JayAPI::Elasticsearch::Script
end
end
end
34 changes: 34 additions & 0 deletions lib/jay_api/elasticsearch/script.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

module JayAPI
module Elasticsearch
# Represents a scripted element in Elasticsearch. This scripted element
# can be used in different places. It can be used in a query clause, but can
# also be used to create custom aggregations or when updating documents.
class Script
attr_reader :source, :lang, :params

# @param [String] source The source for the script element.
# @param [String] lang The language the script is written in.
# @param [Hash] params A +Hash+ with key-value pairs for the script's
# parameters.
def initialize(source:, lang: 'painless', params: nil)
@source = source
@lang = lang

# Keeps the parameters from being modified from the outside after the
# class has been initialized.
@params = params.dup.freeze
end

# @return [Hash] The hash representation of the scripted element.
def to_h
{
source: source,
lang: lang,
params: params
}.compact
end
end
end
end
17 changes: 17 additions & 0 deletions spec/integration/jay_api/elasticsearch/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -364,4 +364,21 @@
expect(method_call).to be(cluster)
end
end

describe '#update' do
let(:method_name) { :update }

let(:client_method_arguments) do
{
index: 'xyz01_integration_test',
id: 'ns4AAZ8BXEjZhYMmw-8y',
body: { doc: { test_case: { owner: 'alice.wolf' } } }
}
end

let(:used_client) { transport_client }
let(:client_method_name) { :update }

it_behaves_like 'JayAPI::Elasticsearch::Client#<any_method>'
end
end
Loading
Loading