Skip to content

Commit 07adeb0

Browse files
Create .synonyms system index (#95548)
Create .synonyms system index that is exposed under es.synonyms_api_feature_flag. This is the first task for creating Synonyms API management, where synonyms will be stored in the .synonyms system index. Relates to #38523
1 parent b6b3da2 commit 07adeb0

File tree

5 files changed

+133
-2
lines changed

5 files changed

+133
-2
lines changed

docs/changelog/95548.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 95548
2+
summary: Create `.synonyms` system index
3+
area: Analysis
4+
type: enhancement
5+
issues: []

docs/reference/migration/apis/feature-migration.asciidoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ Example response:
114114
"migration_status" : "NO_MIGRATION_NEEDED",
115115
"indices" : [ ]
116116
},
117+
{
118+
"feature_name" : "synonyms",
119+
"minimum_index_version" : "8.8.0",
120+
"migration_status" : "NO_MIGRATION_NEEDED",
121+
"indices" : [ ]
122+
},
117123
{
118124
"feature_name" : "tasks",
119125
"minimum_index_version" : "8.0.0",

modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/CommonAnalysisPlugin.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
import org.apache.lucene.analysis.util.ElisionFilter;
101101
import org.apache.lucene.util.SetOnce;
102102
import org.elasticsearch.Version;
103+
import org.elasticsearch.analysis.common.synonyms.SynonymsManagementAPIService;
103104
import org.elasticsearch.client.internal.Client;
104105
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
105106
import org.elasticsearch.cluster.routing.allocation.AllocationService;
@@ -120,12 +121,14 @@
120121
import org.elasticsearch.index.analysis.PreConfiguredTokenizer;
121122
import org.elasticsearch.index.analysis.TokenFilterFactory;
122123
import org.elasticsearch.index.analysis.TokenizerFactory;
124+
import org.elasticsearch.indices.SystemIndexDescriptor;
123125
import org.elasticsearch.indices.analysis.AnalysisModule.AnalysisProvider;
124126
import org.elasticsearch.indices.analysis.PreBuiltCacheFactory.CachingStrategy;
125127
import org.elasticsearch.lucene.analysis.miscellaneous.DisableGraphAttribute;
126128
import org.elasticsearch.plugins.AnalysisPlugin;
127129
import org.elasticsearch.plugins.Plugin;
128130
import org.elasticsearch.plugins.ScriptPlugin;
131+
import org.elasticsearch.plugins.SystemIndexPlugin;
129132
import org.elasticsearch.repositories.RepositoriesService;
130133
import org.elasticsearch.script.ScriptContext;
131134
import org.elasticsearch.script.ScriptService;
@@ -146,8 +149,7 @@
146149

147150
import static org.elasticsearch.plugins.AnalysisPlugin.requiresAnalysisSettings;
148151

149-
public class CommonAnalysisPlugin extends Plugin implements AnalysisPlugin, ScriptPlugin {
150-
152+
public class CommonAnalysisPlugin extends Plugin implements AnalysisPlugin, ScriptPlugin, SystemIndexPlugin {
151153
private static final DeprecationLogger deprecationLogger = DeprecationLogger.getLogger(CommonAnalysisPlugin.class);
152154

153155
private final SetOnce<ScriptService> scriptServiceHolder = new SetOnce<>();
@@ -652,4 +654,23 @@ public List<PreConfiguredTokenizer> getPreConfiguredTokenizers() {
652654

653655
return tokenizers;
654656
}
657+
658+
@Override
659+
public Collection<SystemIndexDescriptor> getSystemIndexDescriptors(Settings settings) {
660+
if (SynonymsManagementAPIService.isEnabled()) {
661+
return Collections.singletonList(SynonymsManagementAPIService.getSystemIndexDescriptor());
662+
} else {
663+
return Collections.emptyList();
664+
}
665+
}
666+
667+
@Override
668+
public String getFeatureName() {
669+
return "synonyms";
670+
}
671+
672+
@Override
673+
public String getFeatureDescription() {
674+
return "Index for storing synonyms managed through APIs";
675+
}
655676
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.analysis.common.synonyms;
10+
11+
import org.elasticsearch.Version;
12+
import org.elasticsearch.cluster.metadata.IndexMetadata;
13+
import org.elasticsearch.common.settings.Settings;
14+
import org.elasticsearch.common.util.FeatureFlag;
15+
import org.elasticsearch.indices.SystemIndexDescriptor;
16+
import org.elasticsearch.xcontent.XContentBuilder;
17+
18+
import java.io.IOException;
19+
import java.io.UncheckedIOException;
20+
21+
import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
22+
import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder;
23+
24+
public class SynonymsManagementAPIService {
25+
private static final FeatureFlag SYNONYMS_API_FEATURE_FLAG = new FeatureFlag("synonyms_api");
26+
public static final String SYNONYMS_INDEX = ".synonyms";
27+
public static final String SYNONYMS_ORIGIN = "synonyms";
28+
29+
public static SystemIndexDescriptor getSystemIndexDescriptor() {
30+
return SystemIndexDescriptor.builder()
31+
.setIndexPattern(SYNONYMS_INDEX + "*")
32+
.setDescription("Synonyms index for synonyms managed through APIs")
33+
.setPrimaryIndex(SYNONYMS_INDEX)
34+
.setMappings(mappings())
35+
.setSettings(settings())
36+
.setVersionMetaKey("version")
37+
.setOrigin(SYNONYMS_ORIGIN)
38+
.build();
39+
}
40+
41+
private static XContentBuilder mappings() {
42+
try {
43+
XContentBuilder builder = jsonBuilder();
44+
builder.startObject();
45+
{
46+
builder.startObject(SINGLE_MAPPING_NAME);
47+
{
48+
builder.startObject("_meta");
49+
{
50+
builder.field("version", Version.CURRENT.toString());
51+
}
52+
builder.endObject();
53+
builder.field("dynamic", "strict");
54+
builder.startObject("properties");
55+
{
56+
builder.startObject("synonyms");
57+
{
58+
builder.field("type", "object");
59+
builder.field("enabled", "false");
60+
}
61+
builder.endObject();
62+
}
63+
builder.endObject();
64+
}
65+
builder.endObject();
66+
}
67+
builder.endObject();
68+
return builder;
69+
} catch (IOException e) {
70+
throw new UncheckedIOException("Failed to build mappings for " + SYNONYMS_INDEX, e);
71+
}
72+
}
73+
74+
static Settings settings() {
75+
return Settings.builder()
76+
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
77+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
78+
.put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-all")
79+
.build();
80+
}
81+
82+
public static boolean isEnabled() {
83+
return SYNONYMS_API_FEATURE_FLAG.isEnabled();
84+
}
85+
}

modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/CommonAnalysisPluginTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
import org.elasticsearch.common.settings.Settings;
1515
import org.elasticsearch.env.Environment;
1616
import org.elasticsearch.index.analysis.TokenizerFactory;
17+
import org.elasticsearch.indices.SystemIndexDescriptor;
1718
import org.elasticsearch.test.ESTestCase;
1819
import org.elasticsearch.test.IndexSettingsModule;
1920
import org.elasticsearch.test.VersionUtils;
2021

2122
import java.io.IOException;
23+
import java.util.List;
2224
import java.util.Map;
2325

26+
import static org.elasticsearch.analysis.common.synonyms.SynonymsManagementAPIService.SYNONYMS_INDEX;
27+
2428
public class CommonAnalysisPluginTests extends ESTestCase {
2529

2630
/**
@@ -220,6 +224,16 @@ public void testNGramTokenizerDeprecation() throws IOException {
220224
);
221225
}
222226

227+
public void testSystemSynonymsIndexName() {
228+
assertEquals(
229+
List.of(SYNONYMS_INDEX),
230+
new CommonAnalysisPlugin().getSystemIndexDescriptors(Settings.EMPTY)
231+
.stream()
232+
.map(SystemIndexDescriptor::getPrimaryIndex)
233+
.toList()
234+
);
235+
}
236+
223237
public void doTestPrebuiltTokenizerDeprecation(String deprecatedName, String replacement, Version version, boolean expectWarning)
224238
throws IOException {
225239
final Settings settings = Settings.builder()

0 commit comments

Comments
 (0)