1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.es.client;
17
18 import static org.codelibs.core.stream.StreamUtil.stream;
19 import static org.codelibs.elasticsearch.runner.ElasticsearchClusterRunner.newConfigs;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.net.InetAddress;
24 import java.net.UnknownHostException;
25 import java.nio.charset.StandardCharsets;
26 import java.text.SimpleDateFormat;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.Date;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.regex.Pattern;
35 import java.util.stream.Collectors;
36
37 import javax.annotation.PostConstruct;
38 import javax.annotation.PreDestroy;
39
40 import org.codelibs.core.beans.util.BeanUtil;
41 import org.codelibs.core.exception.ResourceNotFoundRuntimeException;
42 import org.codelibs.core.io.FileUtil;
43 import org.codelibs.core.io.ResourceUtil;
44 import org.codelibs.core.lang.StringUtil;
45 import org.codelibs.elasticsearch.runner.ElasticsearchClusterRunner;
46 import org.codelibs.elasticsearch.runner.ElasticsearchClusterRunner.Configs;
47 import org.codelibs.elasticsearch.runner.net.Curl;
48 import org.codelibs.elasticsearch.runner.net.CurlResponse;
49 import org.codelibs.fess.Constants;
50 import org.codelibs.fess.entity.FacetInfo;
51 import org.codelibs.fess.entity.GeoInfo;
52 import org.codelibs.fess.entity.PingResponse;
53 import org.codelibs.fess.entity.QueryContext;
54 import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
55 import org.codelibs.fess.exception.FessSystemException;
56 import org.codelibs.fess.exception.InvalidQueryException;
57 import org.codelibs.fess.exception.ResultOffsetExceededException;
58 import org.codelibs.fess.exception.SearchQueryException;
59 import org.codelibs.fess.helper.DocumentHelper;
60 import org.codelibs.fess.helper.QueryHelper;
61 import org.codelibs.fess.mylasta.direction.FessConfig;
62 import org.codelibs.fess.util.ComponentUtil;
63 import org.codelibs.fess.util.DocMap;
64 import org.dbflute.exception.IllegalBehaviorStateException;
65 import org.dbflute.optional.OptionalEntity;
66 import org.elasticsearch.ElasticsearchException;
67 import org.elasticsearch.action.Action;
68 import org.elasticsearch.action.ActionFuture;
69 import org.elasticsearch.action.ActionListener;
70 import org.elasticsearch.action.ActionRequest;
71 import org.elasticsearch.action.ActionRequestBuilder;
72 import org.elasticsearch.action.ActionResponse;
73 import org.elasticsearch.action.DocWriteRequest;
74 import org.elasticsearch.action.DocWriteRequest.OpType;
75 import org.elasticsearch.action.DocWriteResponse.Result;
76 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
77 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
78 import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
79 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
80 import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
81 import org.elasticsearch.action.admin.indices.flush.FlushResponse;
82 import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
83 import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
84 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
85 import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
86 import org.elasticsearch.action.bulk.BulkItemResponse;
87 import org.elasticsearch.action.bulk.BulkItemResponse.Failure;
88 import org.elasticsearch.action.bulk.BulkRequest;
89 import org.elasticsearch.action.bulk.BulkRequestBuilder;
90 import org.elasticsearch.action.bulk.BulkResponse;
91 import org.elasticsearch.action.delete.DeleteRequest;
92 import org.elasticsearch.action.delete.DeleteRequestBuilder;
93 import org.elasticsearch.action.delete.DeleteResponse;
94 import org.elasticsearch.action.explain.ExplainRequest;
95 import org.elasticsearch.action.explain.ExplainRequestBuilder;
96 import org.elasticsearch.action.explain.ExplainResponse;
97 import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
98 import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequestBuilder;
99 import org.elasticsearch.action.fieldcaps.FieldCapabilitiesResponse;
100 import org.elasticsearch.action.fieldstats.FieldStatsRequest;
101 import org.elasticsearch.action.fieldstats.FieldStatsRequestBuilder;
102 import org.elasticsearch.action.fieldstats.FieldStatsResponse;
103 import org.elasticsearch.action.get.GetRequest;
104 import org.elasticsearch.action.get.GetRequestBuilder;
105 import org.elasticsearch.action.get.GetResponse;
106 import org.elasticsearch.action.get.MultiGetRequest;
107 import org.elasticsearch.action.get.MultiGetRequestBuilder;
108 import org.elasticsearch.action.get.MultiGetResponse;
109 import org.elasticsearch.action.index.IndexRequest;
110 import org.elasticsearch.action.index.IndexRequestBuilder;
111 import org.elasticsearch.action.index.IndexResponse;
112 import org.elasticsearch.action.search.ClearScrollRequest;
113 import org.elasticsearch.action.search.ClearScrollRequestBuilder;
114 import org.elasticsearch.action.search.ClearScrollResponse;
115 import org.elasticsearch.action.search.MultiSearchRequest;
116 import org.elasticsearch.action.search.MultiSearchRequestBuilder;
117 import org.elasticsearch.action.search.MultiSearchResponse;
118 import org.elasticsearch.action.search.SearchPhaseExecutionException;
119 import org.elasticsearch.action.search.SearchRequest;
120 import org.elasticsearch.action.search.SearchRequestBuilder;
121 import org.elasticsearch.action.search.SearchResponse;
122 import org.elasticsearch.action.search.SearchScrollRequest;
123 import org.elasticsearch.action.search.SearchScrollRequestBuilder;
124 import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
125 import org.elasticsearch.action.termvectors.MultiTermVectorsRequest;
126 import org.elasticsearch.action.termvectors.MultiTermVectorsRequestBuilder;
127 import org.elasticsearch.action.termvectors.MultiTermVectorsResponse;
128 import org.elasticsearch.action.termvectors.TermVectorsRequest;
129 import org.elasticsearch.action.termvectors.TermVectorsRequestBuilder;
130 import org.elasticsearch.action.termvectors.TermVectorsResponse;
131 import org.elasticsearch.action.update.UpdateRequest;
132 import org.elasticsearch.action.update.UpdateRequestBuilder;
133 import org.elasticsearch.action.update.UpdateResponse;
134 import org.elasticsearch.client.AdminClient;
135 import org.elasticsearch.client.Client;
136 import org.elasticsearch.client.transport.TransportClient;
137 import org.elasticsearch.cluster.metadata.MappingMetaData;
138 import org.elasticsearch.common.collect.ImmutableOpenMap;
139 import org.elasticsearch.common.settings.Settings;
140 import org.elasticsearch.common.settings.Settings.Builder;
141 import org.elasticsearch.common.transport.InetSocketTransportAddress;
142 import org.elasticsearch.common.transport.TransportAddress;
143 import org.elasticsearch.common.unit.TimeValue;
144 import org.elasticsearch.common.xcontent.XContentFactory;
145 import org.elasticsearch.index.query.InnerHitBuilder;
146 import org.elasticsearch.index.query.QueryBuilder;
147 import org.elasticsearch.index.query.QueryBuilders;
148 import org.elasticsearch.search.SearchHit;
149 import org.elasticsearch.search.SearchHitField;
150 import org.elasticsearch.search.SearchHits;
151 import org.elasticsearch.search.aggregations.AggregationBuilders;
152 import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
153 import org.elasticsearch.search.aggregations.bucket.terms.Terms.Order;
154 import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
155 import org.elasticsearch.search.collapse.CollapseBuilder;
156 import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
157 import org.elasticsearch.threadpool.ThreadPool;
158 import org.elasticsearch.transport.client.PreBuiltTransportClient;
159 import org.lastaflute.core.message.UserMessages;
160 import org.slf4j.Logger;
161 import org.slf4j.LoggerFactory;
162
163 import com.fasterxml.jackson.core.type.TypeReference;
164 import com.fasterxml.jackson.databind.ObjectMapper;
165 import com.google.common.io.BaseEncoding;
166
167 public class FessEsClient implements Client {
168 private static final Logger logger = LoggerFactory.getLogger(FessEsClient.class);
169
170 protected ElasticsearchClusterRunner runner;
171
172 protected List<TransportAddress> transportAddressList = new ArrayList<>();
173
174 protected Client client;
175
176 protected Map<String, String> settings;
177
178 protected String indexConfigPath = "fess_indices";
179
180 protected List<String> indexConfigList = new ArrayList<>();
181
182 protected Map<String, List<String>> configListMap = new HashMap<>();
183
184 protected int sizeForDelete = 100;
185
186 protected String scrollForDelete = "1m";
187
188 public void addIndexConfig(final String path) {
189 indexConfigList.add(path);
190 }
191
192 public void addConfigFile(final String index, final String path) {
193 List<String> list = configListMap.get(index);
194 if (list == null) {
195 list = new ArrayList<>();
196 configListMap.put(index, list);
197 }
198 list.add(path);
199 }
200
201 public void setSettings(final Map<String, String> settings) {
202 this.settings = settings;
203 }
204
205 public String getStatus() {
206 return admin().cluster().prepareHealth().execute().actionGet(ComponentUtil.getFessConfig().getIndexHealthTimeout()).getStatus()
207 .name();
208 }
209
210 public void setRunner(final ElasticsearchClusterRunner runner) {
211 this.runner = runner;
212 }
213
214 public boolean isEmbedded() {
215 return this.runner != null;
216 }
217
218 public void addTransportAddress(final String host, final int port) {
219 try {
220 transportAddressList.add(new InetSocketTransportAddress(InetAddress.getByName(host), port));
221 } catch (final UnknownHostException e) {
222 throw new FessSystemException("Failed to resolve the hostname: " + host, e);
223 }
224 }
225
226 @PostConstruct
227 public void open() {
228 final FessConfig fessConfig = ComponentUtil.getFessConfig();
229
230 final String transportAddressesValue = System.getProperty(Constants.FESS_ES_TRANSPORT_ADDRESSES);
231 if (StringUtil.isNotBlank(transportAddressesValue)) {
232 for (final String transportAddressValue : transportAddressesValue.split(",")) {
233 final String[] addressPair = transportAddressValue.trim().split(":");
234 if (addressPair.length < 3) {
235 final String host = addressPair[0];
236 int port = 9300;
237 if (addressPair.length == 2) {
238 port = Integer.parseInt(addressPair[1]);
239 }
240 addTransportAddress(host, port);
241 } else {
242 logger.warn("Invalid address format: " + transportAddressValue);
243 }
244 }
245 }
246
247 if (transportAddressList.isEmpty()) {
248 if (runner == null) {
249 runner = new ElasticsearchClusterRunner();
250 final Configs config = newConfigs().clusterName(fessConfig.getElasticsearchClusterName()).numOfNode(1).useLogger();
251 final String esDir = System.getProperty("fess.es.dir");
252 if (esDir != null) {
253 config.basePath(esDir);
254 }
255 config.disableESLogger();
256 runner.onBuild((number, settingsBuilder) -> {
257 final File pluginDir = new File(esDir, "plugins");
258 if (pluginDir.isDirectory()) {
259 settingsBuilder.put("path.plugins", pluginDir.getAbsolutePath());
260 } else {
261 settingsBuilder.put("path.plugins", new File(System.getProperty("user.dir"), "plugins").getAbsolutePath());
262 }
263 if (settings != null) {
264 settingsBuilder.put(settings);
265 }
266 });
267 runner.build(config);
268 }
269 client = runner.client();
270 addTransportAddress("localhost", runner.node().settings().getAsInt("transport.tcp.port", 9300));
271 } else {
272 final Builder settingsBuilder = Settings.builder();
273 settingsBuilder.put("cluster.name", fessConfig.getElasticsearchClusterName());
274 settingsBuilder.put("client.transport.sniff", fessConfig.isElasticsearchTransportSniff());
275 settingsBuilder.put("client.transport.ping_timeout", fessConfig.getElasticsearchTransportPingTimeout());
276 settingsBuilder.put("client.transport.nodes_sampler_interval", fessConfig.getElasticsearchTransportNodesSamplerInterval());
277 final Settings settings = settingsBuilder.build();
278 final TransportClient transportClient = new PreBuiltTransportClient(settings);
279 for (final TransportAddress address : transportAddressList) {
280 transportClient.addTransportAddress(address);
281 }
282 client = transportClient;
283 }
284
285 if (StringUtil.isBlank(transportAddressesValue)) {
286 final StringBuilder buf = new StringBuilder();
287 for (final TransportAddress transportAddress : transportAddressList) {
288 if (transportAddress instanceof InetSocketTransportAddress) {
289 if (buf.length() > 0) {
290 buf.append(',');
291 }
292 final InetSocketTransportAddress inetTransportAddress = (InetSocketTransportAddress) transportAddress;
293 buf.append(inetTransportAddress.address().getHostName());
294 buf.append(':');
295 buf.append(inetTransportAddress.address().getPort());
296 }
297 }
298 if (buf.length() > 0) {
299 System.setProperty(Constants.FESS_ES_TRANSPORT_ADDRESSES, buf.toString());
300 }
301 }
302
303 waitForYellowStatus();
304
305 indexConfigList.forEach(configName -> {
306 final String[] values = configName.split("/");
307 if (values.length == 2) {
308 final String configIndex = values[0];
309 final String configType = values[1];
310
311 final boolean isFessIndex = configIndex.equals("fess");
312 final String indexName;
313 if (isFessIndex) {
314 final boolean exists = existsIndex(fessConfig.getIndexDocumentUpdateIndex());
315 if (!exists) {
316 indexName = generateNewIndexName(configIndex);
317 createIndex(configIndex, configType, indexName);
318 createAlias(configIndex, indexName);
319 } else {
320 client.admin().cluster().prepareHealth(fessConfig.getIndexDocumentUpdateIndex()).setWaitForYellowStatus().execute()
321 .actionGet(fessConfig.getIndexIndicesTimeout());
322 final GetIndexResponse response =
323 client.admin().indices().prepareGetIndex().addIndices(fessConfig.getIndexDocumentUpdateIndex()).execute()
324 .actionGet(fessConfig.getIndexIndicesTimeout());
325 final String[] indices = response.indices();
326 if (indices.length == 1) {
327 indexName = indices[0];
328 } else {
329 indexName = configIndex;
330 }
331 }
332 } else {
333 switch (configIndex) {
334 case ".fess_config":
335 indexName = fessConfig.getIndexConfigIndex();
336 break;
337 case ".fess_user":
338 indexName = fessConfig.getIndexUserIndex();
339 break;
340 case "fess_log":
341 indexName = fessConfig.getIndexLogIndex();
342 break;
343 default:
344 throw new FessSystemException("Unknown config index: " + configIndex);
345 }
346 final boolean exists = existsIndex(indexName);
347 if (!exists) {
348 createIndex(configIndex, configType, indexName);
349 createAlias(configIndex, indexName);
350 }
351 }
352
353 addMapping(configIndex, configType, indexName);
354 } else {
355 logger.warn("Invalid index config name: " + configName);
356 }
357 });
358 }
359
360 public boolean existsIndex(final String indexName) {
361 final FessConfig fessConfig = ComponentUtil.getFessConfig();
362 boolean exists = false;
363 try {
364 final IndicesExistsResponse response =
365 client.admin().indices().prepareExists(indexName).execute().actionGet(fessConfig.getIndexSearchTimeout());
366 exists = response.isExists();
367 } catch (final Exception e) {
368
369 }
370 return exists;
371 }
372
373 public boolean reindex(final String fromIndex, final String toIndex, final boolean waitForCompletion) {
374 final String source = "{\"source\":{\"index\":\"" + fromIndex + "\"},\"dest\":{\"index\":\"" + toIndex + "\"}}";
375 try (CurlResponse response =
376 Curl.post(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_reindex")
377 .header("Content-Type", "application/json").param("wait_for_completion", Boolean.toString(waitForCompletion))
378 .body(source).execute()) {
379 if (response.getHttpStatusCode() == 200) {
380 return true;
381 } else {
382 logger.warn("Failed to reindex from " + fromIndex + " to " + toIndex);
383 }
384 } catch (final IOException e) {
385 logger.warn("Failed to reindex from " + fromIndex + " to " + toIndex, e);
386 }
387 return false;
388 }
389
390 public boolean createIndex(final String index, final String docType, final String indexName) {
391 final FessConfig fessConfig = ComponentUtil.getFessConfig();
392
393 waitForConfigSyncStatus();
394 sendConfigFiles(index);
395
396 final String indexConfigFile = indexConfigPath + "/" + index + ".json";
397 try {
398 String source = FileUtil.readUTF8(indexConfigFile);
399 String dictionaryPath = System.getProperty("fess.dictionary.path", StringUtil.EMPTY);
400 if (StringUtil.isNotBlank(dictionaryPath) && !dictionaryPath.endsWith("/")) {
401 dictionaryPath = dictionaryPath + "/";
402 }
403 source = source.replaceAll(Pattern.quote("${fess.dictionary.path}"), dictionaryPath);
404 final CreateIndexResponse indexResponse =
405 client.admin().indices().prepareCreate(indexName).setSource(source, XContentFactory.xContentType(source)).execute()
406 .actionGet(fessConfig.getIndexIndicesTimeout());
407 if (indexResponse.isAcknowledged()) {
408 logger.info("Created " + indexName + " index.");
409 return true;
410 } else if (logger.isDebugEnabled()) {
411 logger.debug("Failed to create " + indexName + " index.");
412 }
413 } catch (final Exception e) {
414 logger.warn(indexConfigFile + " is not found.", e);
415 }
416
417 return false;
418 }
419
420 public void addMapping(final String index, final String docType, final String indexName) {
421 final FessConfig fessConfig = ComponentUtil.getFessConfig();
422
423 final GetMappingsResponse getMappingsResponse =
424 client.admin().indices().prepareGetMappings(indexName).execute().actionGet(fessConfig.getIndexIndicesTimeout());
425 final ImmutableOpenMap<String, MappingMetaData> indexMappings = getMappingsResponse.mappings().get(indexName);
426 if (indexMappings == null || !indexMappings.containsKey(docType)) {
427 String source = null;
428 final String mappingFile = indexConfigPath + "/" + index + "/" + docType + ".json";
429 try {
430 source = FileUtil.readUTF8(mappingFile);
431 } catch (final Exception e) {
432 logger.warn(mappingFile + " is not found.", e);
433 }
434 try {
435 final PutMappingResponse putMappingResponse =
436 client.admin().indices().preparePutMapping(indexName).setType(docType)
437 .setSource(source, XContentFactory.xContentType(source)).execute()
438 .actionGet(fessConfig.getIndexIndicesTimeout());
439 if (putMappingResponse.isAcknowledged()) {
440 logger.info("Created " + indexName + "/" + docType + " mapping.");
441 } else {
442 logger.warn("Failed to create " + indexName + "/" + docType + " mapping.");
443 }
444
445 final String dataPath = indexConfigPath + "/" + index + "/" + docType + ".bulk";
446 if (ResourceUtil.isExist(dataPath)) {
447 insertBulkData(fessConfig, indexName, docType, dataPath);
448 }
449 } catch (final Exception e) {
450 logger.warn("Failed to create " + indexName + "/" + docType + " mapping.", e);
451 }
452 } else if (logger.isDebugEnabled()) {
453 logger.debug(indexName + "/" + docType + " mapping exists.");
454 }
455 }
456
457 public boolean updateAlias(final String newIndex) {
458 final FessConfig fessConfig = ComponentUtil.getFessConfig();
459 final String updateAlias = fessConfig.getIndexDocumentUpdateIndex();
460 final String searchAlias = fessConfig.getIndexDocumentSearchIndex();
461 final GetIndexResponse response1 =
462 client.admin().indices().prepareGetIndex().addIndices(updateAlias).execute().actionGet(fessConfig.getIndexIndicesTimeout());
463 final String[] updateIndices = response1.indices();
464 final GetIndexResponse response2 =
465 client.admin().indices().prepareGetIndex().addIndices(searchAlias).execute().actionGet(fessConfig.getIndexIndicesTimeout());
466 final String[] searchIndices = response2.indices();
467
468 final IndicesAliasesRequestBuilder builder =
469 client.admin().indices().prepareAliases().addAlias(newIndex, updateAlias).addAlias(newIndex, searchAlias);
470 for (final String index : updateIndices) {
471 builder.removeAlias(index, updateAlias);
472 }
473 for (final String index : searchIndices) {
474 builder.removeAlias(index, searchAlias);
475 }
476 final IndicesAliasesResponse response = builder.execute().actionGet(fessConfig.getIndexIndicesTimeout());
477 return response.isAcknowledged();
478 }
479
480 protected void createAlias(final String index, final String createdIndexName) {
481 final FessConfig fessConfig = ComponentUtil.getFessConfig();
482
483 final String aliasConfigDirPath = indexConfigPath + "/" + index + "/alias";
484 try {
485 final File aliasConfigDir = ResourceUtil.getResourceAsFile(aliasConfigDirPath);
486 if (aliasConfigDir.isDirectory()) {
487 stream(aliasConfigDir.listFiles((dir, name) -> name.endsWith(".json"))).of(
488 stream -> stream.forEach(f -> {
489 final String aliasName = f.getName().replaceFirst(".json$", "");
490 String source = FileUtil.readUTF8(f);
491 if (source.trim().equals("{}")) {
492 source = null;
493 }
494 final IndicesAliasesResponse response =
495 client.admin().indices().prepareAliases().addAlias(createdIndexName, aliasName, source).execute()
496 .actionGet(fessConfig.getIndexIndicesTimeout());
497 if (response.isAcknowledged()) {
498 logger.info("Created " + aliasName + " alias for " + createdIndexName);
499 } else if (logger.isDebugEnabled()) {
500 logger.debug("Failed to create " + aliasName + " alias for " + createdIndexName);
501 }
502 }));
503 }
504 } catch (final ResourceNotFoundRuntimeException e) {
505
506 } catch (final Exception e) {
507 logger.warn(aliasConfigDirPath + " is not found.", e);
508 }
509 }
510
511 protected void sendConfigFiles(final String index) {
512 configListMap.getOrDefault(index, Collections.emptyList()).forEach(
513 path -> {
514 String source = null;
515 final String filePath = indexConfigPath + "/" + index + "/" + path;
516 try {
517 source = FileUtil.readUTF8(filePath);
518 try (CurlResponse response =
519 Curl.post(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/file")
520 .header("Content-Type", "application/json").param("path", path).body(source).execute()) {
521 if (response.getHttpStatusCode() == 200) {
522 logger.info("Register " + path + " to " + index);
523 } else {
524 if (response.getContentException() != null) {
525 logger.warn("Invalid request for " + path + ".", response.getContentException());
526 } else {
527 logger.warn("Invalid request for " + path + ". The response is " + response.getContentAsString());
528 }
529 }
530 }
531 } catch (final Exception e) {
532 logger.warn("Failed to register " + filePath, e);
533 }
534 });
535 try (CurlResponse response =
536 Curl.post(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/flush")
537 .header("Content-Type", "application/json").execute()) {
538 if (response.getHttpStatusCode() == 200) {
539 logger.info("Flushed config files.");
540 } else {
541 logger.warn("Failed to flush config files.");
542 }
543 } catch (final Exception e) {
544 logger.warn("Failed to flush config files.", e);
545 }
546 }
547
548 protected String generateNewIndexName(final String configIndex) {
549 return configIndex + "." + new SimpleDateFormat("yyyyMMdd").format(new Date());
550 }
551
552 protected void insertBulkData(final FessConfig fessConfig, final String configIndex, final String configType, final String dataPath) {
553 try {
554 final BulkRequestBuilder builder = client.prepareBulk();
555 final ObjectMapper mapper = new ObjectMapper();
556 Arrays.stream(FileUtil.readUTF8(dataPath).split("\n")).reduce(
557 (prev, line) -> {
558 try {
559 if (StringUtil.isBlank(prev)) {
560 final Map<String, Map<String, String>> result =
561 mapper.readValue(line, new TypeReference<Map<String, Map<String, String>>>() {
562 });
563 if (result.keySet().contains("index")) {
564 return line;
565 } else if (result.keySet().contains("update")) {
566 return line;
567 } else if (result.keySet().contains("delete")) {
568 return StringUtil.EMPTY;
569 }
570 } else {
571 final Map<String, Map<String, String>> result =
572 mapper.readValue(prev, new TypeReference<Map<String, Map<String, String>>>() {
573 });
574 if (result.keySet().contains("index")) {
575 final IndexRequestBuilder requestBuilder =
576 client.prepareIndex(configIndex, configType, result.get("index").get("_id")).setSource(line,
577 XContentFactory.xContentType(line));
578 builder.add(requestBuilder);
579 }
580 }
581 } catch (final Exception e) {
582 logger.warn("Failed to parse " + dataPath);
583 }
584 return StringUtil.EMPTY;
585 });
586 final BulkResponse response = builder.execute().actionGet(fessConfig.getIndexBulkTimeout());
587 if (response.hasFailures()) {
588 logger.warn("Failed to register " + dataPath + ": " + response.buildFailureMessage());
589 }
590 } catch (final Exception e) {
591 logger.warn("Failed to create " + configIndex + "/" + configType + " mapping.");
592 }
593 }
594
595 private void waitForYellowStatus() {
596 final ClusterHealthResponse response =
597 client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute()
598 .actionGet(ComponentUtil.getFessConfig().getIndexHealthTimeout());
599 if (logger.isDebugEnabled()) {
600 logger.debug("Elasticsearch Cluster Status: " + response.getStatus());
601 }
602 }
603
604 private void waitForConfigSyncStatus() {
605 try (CurlResponse response =
606 Curl.get(org.codelibs.fess.util.ResourceUtil.getElasticsearchHttpUrl() + "/_configsync/wait")
607 .header("Content-Type", "application/json").param("status", "green").execute()) {
608 if (response.getHttpStatusCode() == 200) {
609 logger.info("ConfigSync is ready.");
610 } else {
611 if (response.getContentException() != null) {
612 throw new FessSystemException("Configsync is not available.", response.getContentException());
613 } else {
614 throw new FessSystemException("Configsync is not available.", response.getContentException());
615 }
616 }
617 } catch (final IOException e) {
618 throw new FessSystemException("Configsync is not available.", e);
619 }
620 }
621
622 @Override
623 @PreDestroy
624 public void close() {
625 try {
626 client.admin().indices().prepareFlush().setForce(true).execute()
627 .actionGet(ComponentUtil.getFessConfig().getIndexIndicesTimeout());
628 } catch (final Exception e) {
629 logger.warn("Failed to flush indices.", e);
630 }
631 try {
632 client.close();
633 } catch (final ElasticsearchException e) {
634 logger.warn("Failed to close Client: " + client, e);
635 }
636 }
637
638 public int deleteByQuery(final String index, final String type, final QueryBuilder queryBuilder) {
639
640 final FessConfig fessConfig = ComponentUtil.getFessConfig();
641 SearchResponse response =
642 client.prepareSearch(index).setTypes(type).setScroll(scrollForDelete).setSize(sizeForDelete)
643 .setFetchSource(new String[] { fessConfig.getIndexFieldId() }, null).setQuery(queryBuilder)
644 .setPreference(Constants.SEARCH_PREFERENCE_PRIMARY).execute()
645 .actionGet(fessConfig.getIndexScrollSearchTimeoutTimeout());
646
647 int count = 0;
648 String scrollId = response.getScrollId();
649 while (scrollId != null) {
650 final SearchHits searchHits = response.getHits();
651 final SearchHit[] hits = searchHits.getHits();
652 if (hits.length == 0) {
653 scrollId = null;
654 break;
655 }
656
657 final BulkRequestBuilder bulkRequest = client.prepareBulk();
658 for (final SearchHit hit : hits) {
659 bulkRequest.add(client.prepareDelete(index, type, hit.getId()));
660 }
661 count += hits.length;
662 final BulkResponse bulkResponse = bulkRequest.execute().actionGet(fessConfig.getIndexBulkTimeout());
663 if (bulkResponse.hasFailures()) {
664 throw new IllegalBehaviorStateException(bulkResponse.buildFailureMessage());
665 }
666
667 response =
668 client.prepareSearchScroll(scrollId).setScroll(scrollForDelete).execute().actionGet(fessConfig.getIndexBulkTimeout());
669 scrollId = response.getScrollId();
670 }
671 return count;
672 }
673
674 protected <T> T get(final String index, final String type, final String id, final SearchCondition<GetRequestBuilder> condition,
675 final SearchResult<T, GetRequestBuilder, GetResponse> searchResult) {
676 final long startTime = System.currentTimeMillis();
677
678 GetResponse response = null;
679 final GetRequestBuilder requestBuilder = client.prepareGet(index, type, id);
680 if (condition.build(requestBuilder)) {
681 response = requestBuilder.execute().actionGet(ComponentUtil.getFessConfig().getIndexSearchTimeout());
682 }
683 final long execTime = System.currentTimeMillis() - startTime;
684
685 return searchResult.build(requestBuilder, execTime, OptionalEntity.ofNullable(response, () -> {}));
686 }
687
688 public <T> T search(final String index, final String type, final SearchCondition<SearchRequestBuilder> condition,
689 final SearchResult<T, SearchRequestBuilder, SearchResponse> searchResult) {
690 final long startTime = System.currentTimeMillis();
691
692 SearchResponse searchResponse = null;
693 final SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type);
694 if (condition.build(searchRequestBuilder)) {
695
696 final FessConfig fessConfig = ComponentUtil.getFessConfig();
697 final long queryTimeout = fessConfig.getQueryTimeoutAsInteger().longValue();
698 if (queryTimeout >= 0) {
699 searchRequestBuilder.setTimeout(TimeValue.timeValueMillis(queryTimeout));
700 }
701
702 try {
703 if (logger.isDebugEnabled()) {
704 logger.debug("Query DSL:\n" + searchRequestBuilder.toString());
705 }
706 searchResponse = searchRequestBuilder.execute().actionGet(ComponentUtil.getFessConfig().getIndexSearchTimeout());
707 } catch (final SearchPhaseExecutionException e) {
708 throw new InvalidQueryException(messages -> messages.addErrorsInvalidQueryParseError(UserMessages.GLOBAL_PROPERTY_KEY),
709 "Invalid query: " + searchRequestBuilder, e);
710 }
711 }
712 final long execTime = System.currentTimeMillis() - startTime;
713
714 return searchResult.build(searchRequestBuilder, execTime, OptionalEntity.ofNullable(searchResponse, () -> {}));
715 }
716
717 public OptionalEntity<Map<String, Object>> getDocument(final String index, final String type,
718 final SearchCondition<SearchRequestBuilder> condition) {
719 return getDocument(
720 index,
721 type,
722 condition,
723 (response, hit) -> {
724 final FessConfig fessConfig = ComponentUtil.getFessConfig();
725 final Map<String, Object> source = hit.getSource();
726 if (source != null) {
727 final Map<String, Object> docMap = new HashMap<>(source);
728 docMap.put(fessConfig.getIndexFieldId(), hit.getId());
729 docMap.put(fessConfig.getIndexFieldVersion(), hit.getVersion());
730 return docMap;
731 }
732 final Map<String, SearchHitField> fields = hit.getFields();
733 if (fields != null) {
734 final Map<String, Object> docMap =
735 fields.entrySet().stream()
736 .collect(Collectors.toMap(e -> e.getKey(), e -> (Object) e.getValue().getValues()));
737 docMap.put(fessConfig.getIndexFieldId(), hit.getId());
738 docMap.put(fessConfig.getIndexFieldVersion(), hit.getVersion());
739 return docMap;
740 }
741 return null;
742 });
743 }
744
745 protected <T> OptionalEntity<T> getDocument(final String index, final String type,
746 final SearchCondition<SearchRequestBuilder> condition, final EntityCreator<T, SearchResponse, SearchHit> creator) {
747 return search(index, type, searchRequestBuilder -> {
748 searchRequestBuilder.setVersion(true);
749 return condition.build(searchRequestBuilder);
750 }, (queryBuilder, execTime, searchResponse) -> {
751 return searchResponse.map(response -> {
752 final SearchHit[] hits = response.getHits().getHits();
753 if (hits.length > 0) {
754 return creator.build(response, hits[0]);
755 }
756 return null;
757 });
758 });
759 }
760
761 public List<Map<String, Object>> getDocumentList(final String index, final String type,
762 final SearchCondition<SearchRequestBuilder> condition) {
763 return getDocumentList(
764 index,
765 type,
766 condition,
767 (response, hit) -> {
768 final FessConfig fessConfig = ComponentUtil.getFessConfig();
769 final Map<String, Object> source = hit.getSource();
770 if (source != null) {
771 final Map<String, Object> docMap = new HashMap<>(source);
772 docMap.put(fessConfig.getIndexFieldId(), hit.getId());
773 return docMap;
774 }
775 final Map<String, SearchHitField> fields = hit.getFields();
776 if (fields != null) {
777 final Map<String, Object> docMap =
778 fields.entrySet().stream()
779 .collect(Collectors.toMap(e -> e.getKey(), e -> (Object) e.getValue().getValues()));
780 docMap.put(fessConfig.getIndexFieldId(), hit.getId());
781 return docMap;
782 }
783 return null;
784 });
785 }
786
787 protected <T> List<T> getDocumentList(final String index, final String type, final SearchCondition<SearchRequestBuilder> condition,
788 final EntityCreator<T, SearchResponse, SearchHit> creator) {
789 return search(index, type, condition, (searchRequestBuilder, execTime, searchResponse) -> {
790 final List<T> list = new ArrayList<>();
791 searchResponse.ifPresent(response -> {
792 response.getHits().forEach(hit -> {
793 list.add(creator.build(response, hit));
794 });
795 });
796 return list;
797 });
798 }
799
800 public boolean update(final String index, final String type, final String id, final String field, final Object value) {
801 try {
802 final Result result =
803 client.prepareUpdate(index, type, id).setDoc(field, value).execute()
804 .actionGet(ComponentUtil.getFessConfig().getIndexIndexTimeout()).getResult();
805 return result == Result.CREATED || result == Result.UPDATED;
806 } catch (final ElasticsearchException e) {
807 throw new FessEsClientException("Failed to set " + value + " to " + field + " for doc " + id, e);
808 }
809 }
810
811 public void refresh(final String... indices) {
812 client.admin().indices().prepareRefresh(indices).execute(new ActionListener<RefreshResponse>() {
813 @Override
814 public void onResponse(final RefreshResponse response) {
815 if (logger.isDebugEnabled()) {
816 logger.debug("Refreshed " + stream(indices).get(stream -> stream.collect(Collectors.joining(", "))) + ".");
817 }
818 }
819
820 @Override
821 public void onFailure(final Exception e) {
822 logger.error("Failed to refresh " + stream(indices).get(stream -> stream.collect(Collectors.joining(", "))) + ".", e);
823 }
824 });
825
826 }
827
828 public void flush(final String... indices) {
829 client.admin().indices().prepareFlush(indices).execute(new ActionListener<FlushResponse>() {
830
831 @Override
832 public void onResponse(final FlushResponse response) {
833 if (logger.isDebugEnabled()) {
834 logger.debug("Flushed " + stream(indices).get(stream -> stream.collect(Collectors.joining(", "))) + ".");
835 }
836 }
837
838 @Override
839 public void onFailure(final Exception e) {
840 logger.error("Failed to flush " + stream(indices).get(stream -> stream.collect(Collectors.joining(", "))) + ".", e);
841 }
842 });
843
844 }
845
846 public PingResponse ping() {
847 try {
848 final ClusterHealthResponse response =
849 client.admin().cluster().prepareHealth().execute().actionGet(ComponentUtil.getFessConfig().getIndexHealthTimeout());
850 return new PingResponse(response);
851 } catch (final ElasticsearchException e) {
852 throw new FessEsClientException("Failed to process a ping request.", e);
853 }
854 }
855
856 public void addAll(final String index, final String type, final List<Map<String, Object>> docList) {
857 final FessConfig fessConfig = ComponentUtil.getFessConfig();
858 final BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
859 for (final Map<String, Object> doc : docList) {
860 final Object id = doc.remove(fessConfig.getIndexFieldId());
861 bulkRequestBuilder.add(client.prepareIndex(index, type, id.toString()).setSource(new DocMap(doc)));
862 }
863 final BulkResponse response = bulkRequestBuilder.execute().actionGet(ComponentUtil.getFessConfig().getIndexBulkTimeout());
864 if (response.hasFailures()) {
865 if (logger.isDebugEnabled()) {
866 @SuppressWarnings("rawtypes")
867 final List<DocWriteRequest> requests = bulkRequestBuilder.request().requests();
868 final BulkItemResponse[] items = response.getItems();
869 if (requests.size() == items.length) {
870 for (int i = 0; i < requests.size(); i++) {
871 final BulkItemResponse resp = items[i];
872 if (resp.isFailed() && resp.getFailure() != null) {
873 final DocWriteRequest<?> req = requests.get(i);
874 final Failure failure = resp.getFailure();
875 logger.debug("Failed Request: " + req + "\n=>" + failure.getMessage());
876 }
877 }
878 }
879 }
880 throw new FessEsClientException(response.buildFailureMessage());
881 }
882 }
883
884 public static class SearchConditionBuilder {
885 private final SearchRequestBuilder searchRequestBuilder;
886 private String query;
887 private String[] responseFields;
888 private int offset = Constants.DEFAULT_START_COUNT;
889 private int size = Constants.DEFAULT_PAGE_SIZE;
890 private GeoInfo geoInfo;
891 private FacetInfo facetInfo;
892 private String similarDocHash;
893 private SearchRequestType searchRequestType = SearchRequestType.SEARCH;
894
895 public static SearchConditionBuilder builder(final SearchRequestBuilder searchRequestBuilder) {
896 return new SearchConditionBuilder(searchRequestBuilder);
897 }
898
899 SearchConditionBuilder(final SearchRequestBuilder searchRequestBuilder) {
900 this.searchRequestBuilder = searchRequestBuilder;
901 }
902
903 public SearchConditionBuilder query(final String query) {
904 this.query = query;
905 return this;
906 }
907
908 public SearchConditionBuilder searchRequestType(final SearchRequestType searchRequestType) {
909 this.searchRequestType = searchRequestType;
910 return this;
911 }
912
913 public SearchConditionBuilder responseFields(final String[] responseFields) {
914 this.responseFields = responseFields;
915 return this;
916 }
917
918 public SearchConditionBuilder offset(final int offset) {
919 this.offset = offset;
920 return this;
921 }
922
923 public SearchConditionBuilder size(final int size) {
924 this.size = size;
925 return this;
926 }
927
928 public SearchConditionBuilder geoInfo(final GeoInfo geoInfo) {
929 this.geoInfo = geoInfo;
930 return this;
931 }
932
933 public SearchConditionBuilder similarDocHash(final String similarDocHash) {
934 if (StringUtil.isNotBlank(similarDocHash)) {
935 this.similarDocHash = similarDocHash;
936 }
937 return this;
938 }
939
940 public SearchConditionBuilder facetInfo(final FacetInfo facetInfo) {
941 this.facetInfo = facetInfo;
942 return this;
943 }
944
945 public boolean build() {
946 if (StringUtil.isBlank(query)) {
947 return false;
948 }
949
950 final QueryHelper queryHelper = ComponentUtil.getQueryHelper();
951 final FessConfig fessConfig = ComponentUtil.getFessConfig();
952
953 if (offset > fessConfig.getQueryMaxSearchResultOffsetAsInteger()) {
954 throw new ResultOffsetExceededException("The number of result size is exceeded.");
955 }
956
957 final QueryContext queryContext =
958 queryHelper.build(searchRequestType, query, context -> {
959 if (SearchRequestType.ADMIN_SEARCH.equals(searchRequestType)) {
960 context.skipRoleQuery();
961 } else if (similarDocHash != null) {
962 final DocumentHelper documentHelper = ComponentUtil.getDocumentHelper();
963 context.addQuery(boolQuery -> {
964 boolQuery.filter(QueryBuilders.termQuery(fessConfig.getIndexFieldContentMinhashBits(),
965 documentHelper.decodeSimilarDocHash(similarDocHash)));
966 });
967 }
968
969 if (geoInfo != null && geoInfo.toQueryBuilder() != null) {
970 context.addQuery(boolQuery -> {
971 boolQuery.filter(geoInfo.toQueryBuilder());
972 });
973 }
974 });
975
976 searchRequestBuilder.setFrom(offset).setSize(size);
977
978 if (responseFields != null) {
979 searchRequestBuilder.setFetchSource(responseFields, null);
980 }
981
982
983 queryContext.sortBuilders().forEach(sortBuilder -> searchRequestBuilder.addSort(sortBuilder));
984
985
986 final HighlightBuilder highlightBuilder = new HighlightBuilder();
987 queryHelper.highlightedFields(stream -> stream.forEach(hf -> highlightBuilder.field(new HighlightBuilder.Field(hf)
988 .highlighterType(fessConfig.getQueryHighlightType()).fragmentSize(fessConfig.getQueryHighlightFragmentSizeAsInteger())
989 .numOfFragments(fessConfig.getQueryHighlightNumberOfFragmentsAsInteger()))));
990 searchRequestBuilder.highlighter(highlightBuilder);
991
992
993 if (facetInfo != null) {
994 stream(facetInfo.field).of(
995 stream -> stream.forEach(f -> {
996 if (queryHelper.isFacetField(f)) {
997 final String encodedField = BaseEncoding.base64().encode(f.getBytes(StandardCharsets.UTF_8));
998 final TermsAggregationBuilder termsBuilder =
999 AggregationBuilders.terms(Constants.FACET_FIELD_PREFIX + encodedField).field(f);
1000 if ("term".equals(facetInfo.sort)) {
1001 termsBuilder.order(Order.term(true));
1002 } else if ("count".equals(facetInfo.sort)) {
1003 termsBuilder.order(Order.count(true));
1004 }
1005 if (facetInfo.size != null) {
1006 termsBuilder.size(facetInfo.size);
1007 }
1008 if (facetInfo.minDocCount != null) {
1009 termsBuilder.minDocCount(facetInfo.minDocCount);
1010 }
1011 if (facetInfo.missing != null) {
1012 termsBuilder.missing(facetInfo.missing);
1013 }
1014 searchRequestBuilder.addAggregation(termsBuilder);
1015 } else {
1016 throw new SearchQueryException("Invalid facet field: " + f);
1017 }
1018 }));
1019 stream(facetInfo.query).of(
1020 stream -> stream.forEach(fq -> {
1021 final QueryContext facetContext = new QueryContext(fq, false);
1022 queryHelper.buildBaseQuery(facetContext, c -> {});
1023 final String encodedFacetQuery = BaseEncoding.base64().encode(fq.getBytes(StandardCharsets.UTF_8));
1024 final FilterAggregationBuilder filterBuilder =
1025 AggregationBuilders.filter(Constants.FACET_QUERY_PREFIX + encodedFacetQuery,
1026 facetContext.getQueryBuilder());
1027 searchRequestBuilder.addAggregation(filterBuilder);
1028 }));
1029 }
1030
1031 if (!SearchRequestType.ADMIN_SEARCH.equals(searchRequestType) && fessConfig.isResultCollapsed() && similarDocHash == null) {
1032 searchRequestBuilder.setCollapse(getCollapseBuilder(fessConfig));
1033 }
1034
1035 searchRequestBuilder.setQuery(queryContext.getQueryBuilder());
1036 return true;
1037 }
1038
1039 protected CollapseBuilder getCollapseBuilder(final FessConfig fessConfig) {
1040 final InnerHitBuilder innerHitBuilder =
1041 new InnerHitBuilder().setName(fessConfig.getQueryCollapseInnerHitsName()).setSize(
1042 fessConfig.getQueryCollapseInnerHitsSizeAsInteger());
1043 fessConfig.getQueryCollapseInnerHitsSortBuilders().ifPresent(
1044 builders -> stream(builders).of(stream -> stream.forEach(innerHitBuilder::addSort)));
1045 return new CollapseBuilder(fessConfig.getIndexFieldContentMinhashBits()).setMaxConcurrentGroupRequests(
1046 fessConfig.getQueryCollapseMaxConcurrentGroupResultsAsInteger()).setInnerHits(innerHitBuilder);
1047 }
1048 }
1049
1050 public boolean store(final String index, final String type, final Object obj) {
1051 final FessConfig fessConfig = ComponentUtil.getFessConfig();
1052 @SuppressWarnings("unchecked")
1053 final Map<String, Object> source = obj instanceof Map ? (Map<String, Object>) obj : BeanUtil.copyBeanToNewMap(obj);
1054 final String id = (String) source.remove(fessConfig.getIndexFieldId());
1055 final Number version = (Number) source.remove(fessConfig.getIndexFieldVersion());
1056 IndexResponse response;
1057 try {
1058 if (id == null) {
1059
1060
1061 response =
1062 client.prepareIndex(index, type).setSource(new DocMap(source)).setRefreshPolicy(RefreshPolicy.IMMEDIATE)
1063 .setOpType(OpType.CREATE).execute().actionGet(fessConfig.getIndexIndexTimeout());
1064 } else {
1065
1066 final IndexRequestBuilder builder =
1067 client.prepareIndex(index, type, id).setSource(new DocMap(source)).setRefreshPolicy(RefreshPolicy.IMMEDIATE)
1068 .setOpType(OpType.INDEX);
1069 if (version != null && version.longValue() > 0) {
1070 builder.setVersion(version.longValue());
1071 }
1072 response = builder.execute().actionGet(fessConfig.getIndexIndexTimeout());
1073 }
1074 final Result result = response.getResult();
1075 return result == Result.CREATED || result == Result.UPDATED;
1076 } catch (final ElasticsearchException e) {
1077 throw new FessEsClientException("Failed to store: " + obj, e);
1078 }
1079 }
1080
1081 public boolean delete(final String index, final String type, final String id, final long version) {
1082 try {
1083 final DeleteRequestBuilder builder = client.prepareDelete(index, type, id).setRefreshPolicy(RefreshPolicy.IMMEDIATE);
1084 if (version > 0) {
1085 builder.setVersion(version);
1086 }
1087 final DeleteResponse response = builder.execute().actionGet(ComponentUtil.getFessConfig().getIndexDeleteTimeout());
1088 return response.getResult() == Result.DELETED;
1089 } catch (final ElasticsearchException e) {
1090 throw new FessEsClientException("Failed to delete: " + index + "/" + type + "/" + id + "/" + version, e);
1091 }
1092 }
1093
1094 public void setIndexConfigPath(final String indexConfigPath) {
1095 this.indexConfigPath = indexConfigPath;
1096 }
1097
1098 public interface SearchCondition<B> {
1099 boolean build(B requestBuilder);
1100 }
1101
1102 public interface SearchResult<T, B, R> {
1103 T build(B requestBuilder, long execTime, OptionalEntity<R> response);
1104 }
1105
1106 public interface EntityCreator<T, R, H> {
1107 T build(R response, H hit);
1108 }
1109
1110
1111
1112
1113
1114 @Override
1115 public ThreadPool threadPool() {
1116 return client.threadPool();
1117 }
1118
1119 @Override
1120 public AdminClient admin() {
1121 return client.admin();
1122 }
1123
1124 @Override
1125 public ActionFuture<IndexResponse> index(final IndexRequest request) {
1126 return client.index(request);
1127 }
1128
1129 @Override
1130 public void index(final IndexRequest request, final ActionListener<IndexResponse> listener) {
1131 client.index(request, listener);
1132 }
1133
1134 @Override
1135 public IndexRequestBuilder prepareIndex() {
1136 return client.prepareIndex();
1137 }
1138
1139 @Override
1140 public ActionFuture<UpdateResponse> update(final UpdateRequest request) {
1141 return client.update(request);
1142 }
1143
1144 @Override
1145 public void update(final UpdateRequest request, final ActionListener<UpdateResponse> listener) {
1146 client.update(request, listener);
1147 }
1148
1149 @Override
1150 public UpdateRequestBuilder prepareUpdate() {
1151 return client.prepareUpdate();
1152 }
1153
1154 @Override
1155 public UpdateRequestBuilder prepareUpdate(final String index, final String type, final String id) {
1156 return client.prepareUpdate(index, type, id);
1157 }
1158
1159 @Override
1160 public IndexRequestBuilder prepareIndex(final String index, final String type) {
1161 return client.prepareIndex(index, type);
1162 }
1163
1164 @Override
1165 public IndexRequestBuilder prepareIndex(final String index, final String type, final String id) {
1166 return client.prepareIndex(index, type, id);
1167 }
1168
1169 @Override
1170 public ActionFuture<DeleteResponse> delete(final DeleteRequest request) {
1171 return client.delete(request);
1172 }
1173
1174 @Override
1175 public void delete(final DeleteRequest request, final ActionListener<DeleteResponse> listener) {
1176 client.delete(request, listener);
1177 }
1178
1179 @Override
1180 public DeleteRequestBuilder prepareDelete() {
1181 return client.prepareDelete();
1182 }
1183
1184 @Override
1185 public DeleteRequestBuilder prepareDelete(final String index, final String type, final String id) {
1186 return client.prepareDelete(index, type, id);
1187 }
1188
1189 @Override
1190 public ActionFuture<BulkResponse> bulk(final BulkRequest request) {
1191 return client.bulk(request);
1192 }
1193
1194 @Override
1195 public void bulk(final BulkRequest request, final ActionListener<BulkResponse> listener) {
1196 client.bulk(request, listener);
1197 }
1198
1199 @Override
1200 public BulkRequestBuilder prepareBulk() {
1201 return client.prepareBulk();
1202 }
1203
1204 @Override
1205 public ActionFuture<GetResponse> get(final GetRequest request) {
1206 return client.get(request);
1207 }
1208
1209 @Override
1210 public void get(final GetRequest request, final ActionListener<GetResponse> listener) {
1211 client.get(request, listener);
1212 }
1213
1214 @Override
1215 public GetRequestBuilder prepareGet() {
1216 return client.prepareGet();
1217 }
1218
1219 @Override
1220 public GetRequestBuilder prepareGet(final String index, final String type, final String id) {
1221 return client.prepareGet(index, type, id);
1222 }
1223
1224 @Override
1225 public ActionFuture<MultiGetResponse> multiGet(final MultiGetRequest request) {
1226 return client.multiGet(request);
1227 }
1228
1229 @Override
1230 public void multiGet(final MultiGetRequest request, final ActionListener<MultiGetResponse> listener) {
1231 client.multiGet(request, listener);
1232 }
1233
1234 @Override
1235 public MultiGetRequestBuilder prepareMultiGet() {
1236 return client.prepareMultiGet();
1237 }
1238
1239 @Override
1240 public ActionFuture<SearchResponse> search(final SearchRequest request) {
1241 return client.search(request);
1242 }
1243
1244 @Override
1245 public void search(final SearchRequest request, final ActionListener<SearchResponse> listener) {
1246 client.search(request, listener);
1247 }
1248
1249 @Override
1250 public SearchRequestBuilder prepareSearch(final String... indices) {
1251 return client.prepareSearch(indices);
1252 }
1253
1254 @Override
1255 public ActionFuture<SearchResponse> searchScroll(final SearchScrollRequest request) {
1256 return client.searchScroll(request);
1257 }
1258
1259 @Override
1260 public void searchScroll(final SearchScrollRequest request, final ActionListener<SearchResponse> listener) {
1261 client.searchScroll(request, listener);
1262 }
1263
1264 @Override
1265 public SearchScrollRequestBuilder prepareSearchScroll(final String scrollId) {
1266 return client.prepareSearchScroll(scrollId);
1267 }
1268
1269 @Override
1270 public ActionFuture<MultiSearchResponse> multiSearch(final MultiSearchRequest request) {
1271 return client.multiSearch(request);
1272 }
1273
1274 @Override
1275 public void multiSearch(final MultiSearchRequest request, final ActionListener<MultiSearchResponse> listener) {
1276 client.multiSearch(request, listener);
1277 }
1278
1279 @Override
1280 public MultiSearchRequestBuilder prepareMultiSearch() {
1281 return client.prepareMultiSearch();
1282 }
1283
1284 @Override
1285 public ExplainRequestBuilder prepareExplain(final String index, final String type, final String id) {
1286 return client.prepareExplain(index, type, id);
1287 }
1288
1289 @Override
1290 public ActionFuture<ExplainResponse> explain(final ExplainRequest request) {
1291 return client.explain(request);
1292 }
1293
1294 @Override
1295 public void explain(final ExplainRequest request, final ActionListener<ExplainResponse> listener) {
1296 client.explain(request, listener);
1297 }
1298
1299 @Override
1300 public ClearScrollRequestBuilder prepareClearScroll() {
1301 return client.prepareClearScroll();
1302 }
1303
1304 @Override
1305 public ActionFuture<ClearScrollResponse> clearScroll(final ClearScrollRequest request) {
1306 return client.clearScroll(request);
1307 }
1308
1309 @Override
1310 public void clearScroll(final ClearScrollRequest request, final ActionListener<ClearScrollResponse> listener) {
1311 client.clearScroll(request, listener);
1312 }
1313
1314 @Override
1315 public FieldStatsRequestBuilder prepareFieldStats() {
1316 return client.prepareFieldStats();
1317 }
1318
1319 @Override
1320 public ActionFuture<FieldStatsResponse> fieldStats(final FieldStatsRequest request) {
1321 return client.fieldStats(request);
1322 }
1323
1324 @Override
1325 public void fieldStats(final FieldStatsRequest request, final ActionListener<FieldStatsResponse> listener) {
1326 client.fieldStats(request, listener);
1327 }
1328
1329 @Override
1330 public Settings settings() {
1331 return client.settings();
1332 }
1333
1334 @Override
1335 public ActionFuture<TermVectorsResponse> termVectors(final TermVectorsRequest request) {
1336 return client.termVectors(request);
1337 }
1338
1339 @Override
1340 public void termVectors(final TermVectorsRequest request, final ActionListener<TermVectorsResponse> listener) {
1341 client.termVectors(request, listener);
1342 }
1343
1344 @Override
1345 public TermVectorsRequestBuilder prepareTermVectors() {
1346 return client.prepareTermVectors();
1347 }
1348
1349 @Override
1350 public TermVectorsRequestBuilder prepareTermVectors(final String index, final String type, final String id) {
1351 return client.prepareTermVectors(index, type, id);
1352 }
1353
1354 @Override
1355 @Deprecated
1356 public ActionFuture<TermVectorsResponse> termVector(final TermVectorsRequest request) {
1357 return client.termVector(request);
1358 }
1359
1360 @Override
1361 @Deprecated
1362 public void termVector(final TermVectorsRequest request, final ActionListener<TermVectorsResponse> listener) {
1363 client.termVector(request, listener);
1364 }
1365
1366 @Override
1367 @Deprecated
1368 public TermVectorsRequestBuilder prepareTermVector() {
1369 return client.prepareTermVector();
1370 }
1371
1372 @Override
1373 @Deprecated
1374 public TermVectorsRequestBuilder prepareTermVector(final String index, final String type, final String id) {
1375 return client.prepareTermVector(index, type, id);
1376 }
1377
1378 @Override
1379 public ActionFuture<MultiTermVectorsResponse> multiTermVectors(final MultiTermVectorsRequest request) {
1380 return client.multiTermVectors(request);
1381 }
1382
1383 @Override
1384 public void multiTermVectors(final MultiTermVectorsRequest request, final ActionListener<MultiTermVectorsResponse> listener) {
1385 client.multiTermVectors(request, listener);
1386 }
1387
1388 @Override
1389 public MultiTermVectorsRequestBuilder prepareMultiTermVectors() {
1390 return client.prepareMultiTermVectors();
1391 }
1392
1393 public void setSizeForDelete(final int sizeForDelete) {
1394 this.sizeForDelete = sizeForDelete;
1395 }
1396
1397 public void setScrollForDelete(final String scrollForDelete) {
1398 this.scrollForDelete = scrollForDelete;
1399 }
1400
1401 @Override
1402 public Client filterWithHeader(final Map<String, String> headers) {
1403 return client.filterWithHeader(headers);
1404 }
1405
1406 @Override
1407 public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> ActionFuture<Response> execute(
1408 final Action<Request, Response, RequestBuilder> action, final Request request) {
1409 return client.execute(action, request);
1410 }
1411
1412 @Override
1413 public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void execute(
1414 final Action<Request, Response, RequestBuilder> action, final Request request, final ActionListener<Response> listener) {
1415 client.execute(action, request, listener);
1416 }
1417
1418 @Override
1419 public <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> RequestBuilder prepareExecute(
1420 final Action<Request, Response, RequestBuilder> action) {
1421 return client.prepareExecute(action);
1422 }
1423
1424 @Override
1425 public FieldCapabilitiesRequestBuilder prepareFieldCaps() {
1426 return client.prepareFieldCaps();
1427 }
1428
1429 @Override
1430 public ActionFuture<FieldCapabilitiesResponse> fieldCaps(final FieldCapabilitiesRequest request) {
1431 return client.fieldCaps(request);
1432 }
1433
1434 @Override
1435 public void fieldCaps(final FieldCapabilitiesRequest request, final ActionListener<FieldCapabilitiesResponse> listener) {
1436 client.fieldCaps(request, listener);
1437 }
1438
1439 }