1
+ /*
2
+ * Licensed to Elasticsearch under one or more contributor
3
+ * license agreements. See the NOTICE file distributed with
4
+ * this work for additional information regarding copyright
5
+ * ownership. Elasticsearch licenses this file to you under
6
+ * the Apache License, Version 2.0 (the "License"); you may
7
+ * not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+
20
+ package org .elasticsearch .analysis .common ;
21
+
22
+ import org .elasticsearch .action .admin .indices .analyze .AnalyzeResponse ;
23
+ import org .elasticsearch .action .admin .indices .analyze .AnalyzeResponse .AnalyzeToken ;
24
+ import org .elasticsearch .action .admin .indices .reloadanalyzer .ReloadAnalyzersResponse ;
25
+ import org .elasticsearch .action .search .SearchResponse ;
26
+ import org .elasticsearch .common .settings .Settings ;
27
+ import org .elasticsearch .env .Environment ;
28
+ import org .elasticsearch .index .query .QueryBuilders ;
29
+ import org .elasticsearch .plugins .Plugin ;
30
+ import org .elasticsearch .test .ESIntegTestCase ;
31
+ import org .elasticsearch .test .InternalTestCluster ;
32
+
33
+ import java .io .FileNotFoundException ;
34
+ import java .io .IOException ;
35
+ import java .io .OutputStreamWriter ;
36
+ import java .io .PrintWriter ;
37
+ import java .nio .charset .StandardCharsets ;
38
+ import java .nio .file .Files ;
39
+ import java .nio .file .Path ;
40
+ import java .nio .file .StandardOpenOption ;
41
+ import java .util .Arrays ;
42
+ import java .util .Collection ;
43
+ import java .util .HashSet ;
44
+ import java .util .Set ;
45
+
46
+ import static org .elasticsearch .test .hamcrest .ElasticsearchAssertions .assertAcked ;
47
+ import static org .elasticsearch .test .hamcrest .ElasticsearchAssertions .assertHitCount ;
48
+ import static org .elasticsearch .test .hamcrest .ElasticsearchAssertions .assertNoFailures ;
49
+
50
+ public class SynonymAnalyzerIT extends ESIntegTestCase {
51
+
52
+ @ Override
53
+ protected Collection <Class <? extends Plugin >> nodePlugins () {
54
+ return Arrays .asList (CommonAnalysisPlugin .class );
55
+ }
56
+
57
+ /**
58
+ * This test needs to write to the config directory, this is difficult in an external cluster so we overwrite this to force running with
59
+ * {@link InternalTestCluster}
60
+ */
61
+ @ Override
62
+ protected boolean ignoreExternalCluster () {
63
+ return true ;
64
+ }
65
+
66
+ public void testSynonymsUpdateable () throws FileNotFoundException , IOException , InterruptedException {
67
+ Path config = internalCluster ().getInstance (Environment .class ).configFile ();
68
+ String synonymsFileName = "synonyms.txt" ;
69
+ Path synonymsFile = config .resolve (synonymsFileName );
70
+ Files .createFile (synonymsFile );
71
+ assertTrue (Files .exists (synonymsFile ));
72
+ try (PrintWriter out = new PrintWriter (
73
+ new OutputStreamWriter (Files .newOutputStream (synonymsFile , StandardOpenOption .CREATE ), StandardCharsets .UTF_8 ))) {
74
+ out .println ("foo, baz" );
75
+ }
76
+ assertAcked (client ().admin ().indices ().prepareCreate ("test" ).setSettings (Settings .builder ()
77
+ .put ("index.number_of_shards" , cluster ().numDataNodes () * 2 )
78
+ .put ("index.number_of_replicas" , 1 )
79
+ .put ("analysis.analyzer.my_synonym_analyzer.tokenizer" , "standard" )
80
+ .put ("analysis.analyzer.my_synonym_analyzer.filter" , "my_synonym_filter" )
81
+ .put ("analysis.filter.my_synonym_filter.type" , "synonym" )
82
+ .put ("analysis.filter.my_synonym_filter.updateable" , "true" )
83
+ .put ("analysis.filter.my_synonym_filter.synonyms_path" , synonymsFileName ))
84
+ .addMapping ("_doc" , "field" , "type=text,analyzer=standard,search_analyzer=my_synonym_analyzer" ));
85
+
86
+ client ().prepareIndex ("test" , "_doc" , "1" ).setSource ("field" , "foo" ).get ();
87
+ assertNoFailures (client ().admin ().indices ().prepareRefresh ("test" ).execute ().actionGet ());
88
+
89
+ SearchResponse response = client ().prepareSearch ("test" ).setQuery (QueryBuilders .matchQuery ("field" , "baz" )).get ();
90
+ assertHitCount (response , 1L );
91
+ response = client ().prepareSearch ("test" ).setQuery (QueryBuilders .matchQuery ("field" , "buzz" )).get ();
92
+ assertHitCount (response , 0L );
93
+ AnalyzeResponse analyzeResponse = client ().admin ().indices ().prepareAnalyze ("test" , "foo" ).setAnalyzer ("my_synonym_analyzer" ).get ();
94
+ assertEquals (2 , analyzeResponse .getTokens ().size ());
95
+ assertEquals ("foo" , analyzeResponse .getTokens ().get (0 ).getTerm ());
96
+ assertEquals ("baz" , analyzeResponse .getTokens ().get (1 ).getTerm ());
97
+
98
+ // now update synonyms file several times and trigger reloading
99
+ for (int i = 0 ; i < 10 ; i ++) {
100
+ String testTerm = randomAlphaOfLength (10 );
101
+ try (PrintWriter out = new PrintWriter (
102
+ new OutputStreamWriter (Files .newOutputStream (synonymsFile , StandardOpenOption .WRITE ), StandardCharsets .UTF_8 ))) {
103
+ out .println ("foo, baz, " + testTerm );
104
+ }
105
+ ReloadAnalyzersResponse reloadResponse = client ().admin ().indices ().prepareReloadAnalyzers ("test" ).execute ().actionGet ();
106
+ assertNoFailures (reloadResponse );
107
+ assertEquals (cluster ().numDataNodes (), reloadResponse .getSuccessfulShards ());
108
+
109
+ analyzeResponse = client ().admin ().indices ().prepareAnalyze ("test" , "foo" ).setAnalyzer ("my_synonym_analyzer" ).get ();
110
+ assertEquals (3 , analyzeResponse .getTokens ().size ());
111
+ Set <String > tokens = new HashSet <>();
112
+ analyzeResponse .getTokens ().stream ().map (AnalyzeToken ::getTerm ).forEach (t -> tokens .add (t ));
113
+ assertTrue (tokens .contains ("foo" ));
114
+ assertTrue (tokens .contains ("baz" ));
115
+ assertTrue (tokens .contains (testTerm ));
116
+
117
+ response = client ().prepareSearch ("test" ).setQuery (QueryBuilders .matchQuery ("field" , "baz" )).get ();
118
+ assertHitCount (response , 1L );
119
+ response = client ().prepareSearch ("test" ).setQuery (QueryBuilders .matchQuery ("field" , testTerm )).get ();
120
+ assertHitCount (response , 1L );
121
+ }
122
+ }
123
+ }
0 commit comments