package com.codetroopers.play.elasticsearch; import com.codetroopers.play.elasticsearch.jest.*; import io.searchbox.indices.*; import io.searchbox.indices.mapping.GetMapping; import io.searchbox.indices.mapping.PutMapping; import org.apache.commons.lang3.StringUtils; import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.index.query.FilterBuilder; import org.elasticsearch.percolator.PercolatorService; import play.Logger; import play.libs.F; import javax.validation.constraints.NotNull; import java.util.Collection; import java.util.List; import java.util.Map; import static com.codetroopers.play.elasticsearch.jest.JestClientWrapper.execute; import static com.codetroopers.play.elasticsearch.jest.JestClientWrapper.log; public abstract class IndexService { public static final String INDEX_DEFAULT = IndexClient.config.indexNames[0]; public static final String TYPE_NAME_PERCOLATOR = PercolatorService.TYPE_NAME; /** * get indexRequest to index from a specific request * * @return */ public static JestIndexRequestBuilder getIndexRequest(IndexQueryPath indexPath, String id, Index indexable) { return new JestIndexRequestBuilder(indexPath.index) .setType(indexPath.type) .setId(id) .setSource(indexable.toIndex()); } /** * index from an request * * @param requestBuilder * @return */ @NotNull public static JestRichResult index(JestIndexRequestBuilder requestBuilder) { JestRichResult jestResult = execute(requestBuilder); log(jestResult, "index"); return jestResult; } /** * Create an JestIndexRequestBuilder * * @param indexPath * @param id * @param indexable * @return */ private static JestIndexRequestBuilder getJestIndexRequestBuilder(IndexQueryPath indexPath, String id, Index indexable) { return getIndexRequest(indexPath, id, indexable); } /** * Add Indexable object in the index * * @param indexPath * @param indexable * @return */ @NotNull public static JestRichResult index(IndexQueryPath indexPath, String id, Index indexable) { JestRichResult jestResult = getJestIndexRequestBuilder(indexPath, id, indexable).execute(); log(jestResult, "index"); return jestResult; } /** * Add Indexable object in the index asynchronously * * @param indexPath * @param indexable * @return */ public static F.Promise<JestRichResult> indexAsync(IndexQueryPath indexPath, String id, Index indexable) { return getJestIndexRequestBuilder(indexPath, id, indexable).executeAsync(); } /** * call JestIndexRequestBuilder on asynchronously * * @param jestIndexRequestBuilder * @return */ public static F.Promise<JestRichResult> indexAsync(JestIndexRequestBuilder jestIndexRequestBuilder) { return jestIndexRequestBuilder.executeAsync(); } /** * Add a json document to the index * * @param indexPath * @param id * @param json * @return */ @NotNull public static JestRichResult index(IndexQueryPath indexPath, String id, String json) { return getJestIndexRequestBuilder(indexPath, id, json).execute(); } /** * Create an JestIndexRequestBuilder for a Json-encoded object * * @param indexPath * @param id * @param json * @return */ public static JestIndexRequestBuilder getJestIndexRequestBuilder(IndexQueryPath indexPath, String id, String json) { return new JestIndexRequestBuilder(indexPath.index) .setType(indexPath.type) .setId(id) .setSource(json); } /** * Create a BulkRequestBuilder for a List of Index objects * * @param indexPath * @param indexables * @return */ private static JestBulkRequestBuilder getBulkRequestBuilder(IndexQueryPath indexPath, List<? extends Index> indexables) { final JestBulkRequestBuilder jestBulkRequestBuilder = new JestBulkRequestBuilder(); for (Index indexable : indexables) { jestBulkRequestBuilder.add(getJestIndexRequestBuilder(indexPath, indexable.id, indexable).getAction()); } return jestBulkRequestBuilder; } /** * Bulk index a list of indexables * * @param indexPath * @param indexables * @return */ public static JestRichResult indexBulk(IndexQueryPath indexPath, List<? extends Index> indexables) { JestBulkRequestBuilder bulkRequestBuilder = getBulkRequestBuilder(indexPath, indexables); return bulkRequestBuilder.execute(); } /** * Bulk index a list of indexables asynchronously * * @param indexPath * @param indexables * @return */ public static F.Promise<JestRichResult> indexBulkAsync(IndexQueryPath indexPath, List<? extends Index> indexables) { return getBulkRequestBuilder(indexPath, indexables).executeAsync(); } /** * Create a BulkRequestBuilder for a List of json-encoded objects * * @param indexPath * @param jsonMap * @return */ public static JestBulkRequestBuilder getBulkRequestBuilder(IndexQueryPath indexPath, Map<String, String> jsonMap) { JestBulkRequestBuilder bulkRequestBuilder = new JestBulkRequestBuilder(); for (String id : jsonMap.keySet()) { bulkRequestBuilder.add(getJestIndexRequestBuilder(indexPath, id, jsonMap.get(id))); } return bulkRequestBuilder; } /** * Bulk index a list of indexables asynchronously * * @param bulkRequestBuilder * @return */ public static F.Promise<JestRichResult> indexBulkAsync(JestBulkRequestBuilder bulkRequestBuilder) { return bulkRequestBuilder.executeAsync(); } /** * Create a BulkRequestBuilder for a List of JestIndexRequestBuilder * * @return */ public static JestBulkRequestBuilder getBulkRequestBuilder(Collection<JestIndexRequestBuilder> JestIndexRequestBuilder) { JestBulkRequestBuilder bulkRequestBuilder = new JestBulkRequestBuilder(); for (JestIndexRequestBuilder requestBuilder : JestIndexRequestBuilder) { bulkRequestBuilder.add(requestBuilder); } return bulkRequestBuilder; } /** * Bulk index a Map of json documents. * The id of the document is the key of the Map * * @param indexPath * @param jsonMap * @return */ public static JestRichResult indexBulk(IndexQueryPath indexPath, Map<String, String> jsonMap) { JestBulkRequestBuilder bulkRequestBuilder = getBulkRequestBuilder(indexPath, jsonMap); return bulkRequestBuilder.execute(); } /** * Create an UpdateRequestBuilder * * @param indexPath * @param id * @return */ public static JestUpdateRequestBuilder getUpdateRequestBuilder(IndexQueryPath indexPath, String id, Map<String, Object> updateFieldValues, String updateScript) { return new JestUpdateRequestBuilder(indexPath.index, indexPath.type, id).setScriptParams(updateFieldValues).setScript(updateScript); } /** * Update a document in the index * * @param indexPath * @param id * @param updateFieldValues The fields and new values for which the update should be done * @param updateScript * @return */ public static JestRichResult update(IndexQueryPath indexPath, String id, Map<String, Object> updateFieldValues, String updateScript) { return getUpdateRequestBuilder(indexPath, id, updateFieldValues, updateScript).execute(); } /** * Update a document asynchronously * * @param indexPath * @param id * @param updateFieldValues The fields and new values for which the update should be done * @param updateScript * @return */ public static F.Promise<JestRichResult> updateAsync(IndexQueryPath indexPath, String id, Map<String, Object> updateFieldValues, String updateScript) { return getUpdateRequestBuilder(indexPath, id, updateFieldValues, updateScript).executeAsync(); } /** * Call update asynchronously * * @param updateRequestBuilder * @return */ public static F.Promise<JestRichResult> updateAsync(JestUpdateRequestBuilder updateRequestBuilder) { return updateRequestBuilder.executeAsync(); } /** * Create a DeleteRequestBuilder * * @param indexPath * @param id * @return */ public static JestDeleteRequestBuilder getDeleteRequestBuilder(IndexQueryPath indexPath, String id) { return new JestDeleteRequestBuilder(indexPath.index, indexPath.type, id); } /** * Delete element in index asynchronously * * @param indexPath * @return */ public static F.Promise<JestRichResult> deleteAsync(IndexQueryPath indexPath, String id) { return getDeleteRequestBuilder(indexPath, id).executeAsync(); } /** * Delete element in index * * @param indexPath * @return */ @NotNull public static JestRichResult delete(IndexQueryPath indexPath, String id) { JestRichResult deleteResponse = getDeleteRequestBuilder(indexPath, id).execute(); log(deleteResponse, "delete"); return deleteResponse; } /** * Create a GetRequestBuilder * * @param indexPath * @param id * @return */ public static JestGetRequestBuilder getGetRequestBuilder(IndexQueryPath indexPath, String id) { return new JestGetRequestBuilder(indexPath.index, indexPath.type, id); } /** * Get the json representation of a document from an id * * @param indexPath * @param id * @return */ @NotNull public static String getAsString(IndexQueryPath indexPath, String id) { final JestRichResult jestResult = getGetRequestBuilder(indexPath, id).execute(); if (jestResult != null) { return jestResult.getJsonString(); } return ""; } @NotNull private static <T extends Index> T getTFromGetResponse(Class<T> clazz, JestRichResult getResponse) { if (!getResponse.isSucceeded()) { return null; } return getResponse.getFirstHit(clazz); } /** * Get Indexable Object for an Id * * @param indexPath * @param clazz * @return */ public static <T extends Index> T get(IndexQueryPath indexPath, Class<T> clazz, String id) { JestGetRequestBuilder getRequestBuilder = getGetRequestBuilder(indexPath, id); return getTFromGetResponse(clazz, getRequestBuilder.execute()); } /** * Get Indexable Object for an Id asynchronously * * @param indexPath * @param clazz * @param id * @param <T> * @return */ @NotNull public static <T extends Index> F.Promise<T> getAsync(IndexQueryPath indexPath, final Class<T> clazz, String id) { final F.Promise<JestRichResult> jestResultPromise = getGetRequestBuilder(indexPath, id).executeAsync(); return jestResultPromise.map( new F.Function<JestRichResult, T>() { public T apply(JestRichResult getResponse) { return getTFromGetResponse(clazz, getResponse); } } ); } /** * Get a reponse for a simple request * * @param indexName * @param indexType * @param id * @return */ public static JestRichResult get(String indexName, String indexType, String id) { return new JestGetRequestBuilder(indexName, indexType, id).execute(); } /** * Search information on Index from a query * * @param indexQuery * @param <T> * @return */ public static <T extends Index> IndexResults<T> search(IndexQueryPath indexPath, IndexQuery<T> indexQuery) { return indexQuery.fetch(indexPath); } /** * Search asynchronously information on Index from a query * * @param indexPath * @param indexQuery * @param <T> * @return */ public static <T extends Index> F.Promise<IndexResults<T>> searchAsync(IndexQueryPath indexPath, IndexQuery<T> indexQuery, FilterBuilder filter) { return indexQuery.fetchAsync(indexPath, filter); } /** * Test if an indice Exists * * @return true if exists */ public static boolean existsIndex(String indexName) { final JestRichResult jestResult = execute(new IndicesExists.Builder(indexName).build()); return jestResult != null && jestResult.isSucceeded(); } /** * Create the index */ public static void createIndex(String indexName) { Logger.debug("ElasticSearch : creating index [" + indexName + "]"); final String jsonNode = IndexClient.config.indexSettings.get(indexName); final CreateIndex.Builder builder = new CreateIndex.Builder(indexName); if (StringUtils.isNotBlank(jsonNode)) { final ImmutableMap<String, String> settings = ImmutableSettings.builder().loadFromSource(jsonNode).build().getAsMap(); builder.settings(settings); } final JestRichResult jestResult = execute(builder.build()); log(jestResult, "index creation result =>"); } /** * Delete the index */ public static void deleteIndex(String indexName) { Logger.debug("ElasticSearch : deleting index [" + indexName + "]"); final DeleteIndex.Builder builder = new DeleteIndex.Builder(indexName); execute(builder.build()); } /** * Create Mapping ( for example mapping type : nested, geo_point ) * see http://www.elasticsearch.org/guide/reference/mapping/ * <p/> * { * "tweet" : { * "properties" : { * "message" : {"type" : "string", "store" : "yes"} * } * } * } * @param indexName * @param indexType * @param indexMapping */ public static JestRichResult createMapping(String indexName, String indexType, String indexMapping) { Logger.debug("ElasticSearch : creating mapping [" + indexName + "/" + indexType + "] : " + indexMapping); final PutMapping build = new PutMapping.Builder(indexName, indexType, indexMapping).build(); return execute(build); } /** * Read the Mapping for a type * * @param indexType * @return */ @NotNull public static String getMapping(String indexName, String indexType) { final GetMapping build = new GetMapping.Builder().addIndex(indexName).addType(indexType).build(); final JestRichResult jestResult = execute(build); if (jestResult != null) { return jestResult.getJsonString(); } return ""; } /** * call createMapping for list of @indexType * * @param indexName */ public static void prepareIndex(String indexName) { Map<IndexQueryPath, String> indexMappings = IndexClient.config.indexMappings; for (IndexQueryPath indexQueryPath : indexMappings.keySet()) { if (indexName != null && indexName.equals(indexQueryPath.index)) { String indexType = indexQueryPath.type; String indexMapping = indexMappings.get(indexQueryPath); if (indexMapping != null) { createMapping(indexName, indexType, indexMapping); } } } } public static void cleanIndex() { String[] indexNames = IndexClient.config.indexNames; for (String indexName : indexNames) { cleanIndex(indexName); } } public static void cleanIndex(String indexName) { if (IndexService.existsIndex(indexName)) { IndexService.deleteIndex(indexName); } IndexService.createIndex(indexName); IndexService.prepareIndex(indexName); } /** * Refresh full index */ public static void refresh() { String[] indexNames = IndexClient.config.indexNames; for (String indexName : indexNames) { refresh(indexName); } } /** * Refresh an index * * @param indexName */ private static void refresh(String indexName) { execute(new Refresh.Builder().addIndex(indexName).build()); } /** * Flush full index */ public static void flush() { String[] indexNames = IndexClient.config.indexNames; for (String indexName : indexNames) { flush(indexName); } } /** * Flush an index * * @param indexName */ public static void flush(String indexName) { execute(new Flush.Builder().addIndex(indexName).build()); } }