Skip to content

Auto-reload synonym analyzers on synonyms updates #96886

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
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
2 changes: 1 addition & 1 deletion modules/analysis-common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ esplugin {

restResources {
restApi {
include '_common', 'indices', 'index', 'cluster', 'search', 'nodes', 'bulk', 'termvectors', 'explain', 'count', 'synonyms.put'
include '_common', 'indices', 'index', 'cluster', 'search', 'nodes', 'bulk', 'termvectors', 'explain', 'count', 'synonyms.put', 'synonyms.delete'
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
---
"Load synonyms from index for an analyzer":
"Load and auto-reload synonyms from index for an analyzer":
- skip:
version: " - 8.8.99"
reason: Loading synonyms from index is introduced in 8.9.0

# Create a new synonyms set
- do:
synonyms.put:
synonyms_set: set1
body:
synonyms_set:
- synonyms: "hello, hi"
- synonyms: "bye => goodbye"

- match: { result: "created" }

# Create an index with synonym_filter that uses that synonyms set
- do:
indices.create:
index: my_index
Expand Down Expand Up @@ -46,6 +48,7 @@
- '{"index": {"_index": "my_index", "_id": "2"}}'
- '{"my_field": "goodbye"}'

# Confirm that synonyms from the synonyms set are used
- do:
search:
index: my_index
Expand All @@ -66,6 +69,71 @@
query: bye
- match: { hits.total.value: 1 }

# Update synonyms and check reload status
- do:
synonyms.put:
synonyms_set: set1
body:
synonyms_set:
- synonyms: "hello, salute"
- synonyms: "ciao => goodbye"
- match: { result: "updated" }
- gte: { reload_analyzers_details._shards.total: 1 }
- match: { reload_analyzers_details.reload_details.0.index: "my_index" }
- match: { reload_analyzers_details.reload_details.0.reloaded_analyzers.0 : "my_analyzer" }

# Confirm that the index analyzers are reloaded
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this test ❤️

- do:
search:
index: my_index
body:
query:
match:
my_field:
query: salute
- match: { hits.total.value: 1 }

- do:
search:
index: my_index
body:
query:
match:
my_field:
query: ciao
- match: { hits.total.value: 1 }

# Delete the synonyms set and confirm failed reload analyzers details
- do:
synonyms.delete:
synonyms_set: set1

- match:
acknowledged: true
- gte: { reload_analyzers_details._shards.failed: 1 }
- match: { reload_analyzers_details._shards.failures.0.index: "my_index" }
- match: { reload_analyzers_details._shards.failures.0.reason.reason: "Synonym set [set1] not found" }

# Confirm that the index analyzers are not reloaded and still using old synonyms
- do:
search:
index: my_index
body:
query:
match:
my_field:
query: salute
- match: { hits.total.value: 1 }

- do:
search:
index: my_index
body:
query:
match:
my_field:
query: ciao
- match: { hits.total.value: 1 }

---
"Fail loading synonyms from index if synonyms_set doesn't exist":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
id: "test-id"

- match: { result: "created" }
- match: { reload_analyzers_details._shards.total: 0 }
- length: { reload_analyzers_details.reload_details: 0 }

- do:
synonyms.put:
Expand All @@ -22,6 +24,8 @@
- synonyms: "other, another"

- match: { result: "updated" }
- match: { reload_analyzers_details._shards.total: 0 }
- length: { reload_analyzers_details.reload_details: 0 }

---
"Validation fails tests":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ setup:

- match:
acknowledged: true
- match: { reload_analyzers_details._shards.total: 0 }
- length: { reload_analyzers_details.reload_details: 0 }

- do:
catch: missing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,28 @@
import org.apache.logging.log4j.util.Strings;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.xcontent.ToXContent;
import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContentBuilder;

import java.io.IOException;
import java.util.Objects;

public class DeleteSynonymsAction extends ActionType<AcknowledgedResponse> {
import static org.elasticsearch.action.support.master.AcknowledgedResponse.ACKNOWLEDGED_KEY;

public class DeleteSynonymsAction extends ActionType<DeleteSynonymsAction.Response> {

public static final DeleteSynonymsAction INSTANCE = new DeleteSynonymsAction();
public static final String NAME = "cluster:admin/synonyms/delete";

public DeleteSynonymsAction() {
super(NAME, AcknowledgedResponse::readFrom);
super(NAME, Response::new);
}

public static class Request extends ActionRequest {
Expand Down Expand Up @@ -71,4 +78,56 @@ public int hashCode() {
return Objects.hash(synonymsSetId);
}
}

public static class Response extends ActionResponse implements ToXContentObject {

private final AcknowledgedResponse acknowledgedResponse;
private final ReloadAnalyzersResponse reloadAnalyzersResponse;

public Response(StreamInput in) throws IOException {
super(in);
this.acknowledgedResponse = AcknowledgedResponse.readFrom(in);
this.reloadAnalyzersResponse = new ReloadAnalyzersResponse(in);
}

public Response(AcknowledgedResponse acknowledgedResponse, ReloadAnalyzersResponse reloadAnalyzersResponse) {
super();
Objects.requireNonNull(acknowledgedResponse, "Acknowledge response must not be null");
Objects.requireNonNull(reloadAnalyzersResponse, "Reload analyzers response must not be null");
this.acknowledgedResponse = acknowledgedResponse;
this.reloadAnalyzersResponse = reloadAnalyzersResponse;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
builder.startObject();
{
builder.field(ACKNOWLEDGED_KEY, acknowledgedResponse.isAcknowledged());
builder.field("reload_analyzers_details");
reloadAnalyzersResponse.toXContent(builder, params);
}
builder.endObject();
return builder;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
acknowledgedResponse.writeTo(out);
reloadAnalyzersResponse.writeTo(out);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Response response = (Response) o;
return Objects.equals(acknowledgedResponse, response.acknowledgedResponse)
&& Objects.equals(reloadAnalyzersResponse, response.reloadAnalyzersResponse);
}

@Override
public int hashCode() {
return Objects.hash(acknowledgedResponse, reloadAnalyzersResponse);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.ValidateActions;
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponse;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
Expand All @@ -22,6 +23,7 @@
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.synonyms.SynonymRule;
import org.elasticsearch.synonyms.SynonymsManagementAPIService;
import org.elasticsearch.synonyms.SynonymsManagementAPIService.UpdateSynonymsResultStatus;
import org.elasticsearch.xcontent.ConstructingObjectParser;
import org.elasticsearch.xcontent.ParseField;
import org.elasticsearch.xcontent.ToXContent;
Expand Down Expand Up @@ -121,36 +123,42 @@ public int hashCode() {

public static class Response extends ActionResponse implements StatusToXContentObject {

private final SynonymsManagementAPIService.UpdateSynonymsResult result;
private final UpdateSynonymsResultStatus updateStatus;
private final ReloadAnalyzersResponse reloadAnalyzersResponse;

public Response(StreamInput in) throws IOException {
super(in);
this.result = in.readEnum((SynonymsManagementAPIService.UpdateSynonymsResult.class));
this.updateStatus = in.readEnum(UpdateSynonymsResultStatus.class);
this.reloadAnalyzersResponse = new ReloadAnalyzersResponse(in);
}

public Response(SynonymsManagementAPIService.UpdateSynonymsResult result) {
public Response(UpdateSynonymsResultStatus updateStatus, ReloadAnalyzersResponse reloadAnalyzersResponse) {
super();
Objects.requireNonNull(result, "Result must not be null");
this.result = result;
Objects.requireNonNull(updateStatus, "Update status must not be null");
Objects.requireNonNull(updateStatus, "Reload analyzers response must not be null");
this.updateStatus = updateStatus;
this.reloadAnalyzersResponse = reloadAnalyzersResponse;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
builder.startObject();
builder.field("result", result.name().toLowerCase(Locale.ENGLISH));
builder.field("result", updateStatus.name().toLowerCase(Locale.ENGLISH));
builder.field("reload_analyzers_details");
reloadAnalyzersResponse.toXContent(builder, params);
builder.endObject();

return builder;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeEnum(result);
out.writeEnum(updateStatus);
reloadAnalyzersResponse.writeTo(out);
}

@Override
public RestStatus status() {
return switch (result) {
return switch (updateStatus) {
case CREATED -> RestStatus.CREATED;
default -> RestStatus.OK;
};
Expand All @@ -161,12 +169,12 @@ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Response response = (Response) o;
return result == response.result;
return updateStatus == response.updateStatus && Objects.equals(reloadAnalyzersResponse, response.reloadAnalyzersResponse);
}

@Override
public int hashCode() {
return Objects.hash(result);
return Objects.hash(updateStatus, reloadAnalyzersResponse);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.HandledTransportAction;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.internal.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.synonyms.SynonymsManagementAPIService;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.transport.TransportService;

public class TransportDeleteSynonymsAction extends HandledTransportAction<DeleteSynonymsAction.Request, AcknowledgedResponse> {
public class TransportDeleteSynonymsAction extends HandledTransportAction<DeleteSynonymsAction.Request, DeleteSynonymsAction.Response> {

private final SynonymsManagementAPIService synonymsManagementAPIService;

Expand All @@ -30,7 +29,10 @@ public TransportDeleteSynonymsAction(TransportService transportService, ActionFi
}

@Override
protected void doExecute(Task task, DeleteSynonymsAction.Request request, ActionListener<AcknowledgedResponse> listener) {
synonymsManagementAPIService.deleteSynonymsSet(request.synonymsSetId(), listener);
protected void doExecute(Task task, DeleteSynonymsAction.Request request, ActionListener<DeleteSynonymsAction.Response> listener) {
synonymsManagementAPIService.deleteSynonymsSet(
request.synonymsSetId(),
listener.map(dr -> new DeleteSynonymsAction.Response(dr.acknowledgedResponse(), dr.reloadAnalyzersResponse()))
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected void doExecute(Task task, PutSynonymsAction.Request request, ActionLis
synonymsManagementAPIService.putSynonymsSet(
request.synonymsSetId(),
request.synonymRules(),
listener.map(PutSynonymsAction.Response::new)
listener.map(ur -> new PutSynonymsAction.Response(ur.updateStatus(), ur.reloadAnalyzersResponse()))
);
}
}
Loading