Skip to content

Commit

Permalink
Merge remote-tracking branch 'org_elastic/master'
Browse files Browse the repository at this point in the history
* org_elastic/master: (28 commits)
  0.4 release
  Add MapperTransformer
  Use AbstractFieldMapper#getFieldValue()
  Some refactoring; Mapper prefix folded into AbstractFieldMapper
  feliperazeek#32 Added a transformer which uses a mapper
  Make sure the user has not requested unknown fields
  Minor restructuring
  Made AFM#addField() non-static so we can access meta directly
  Log json for index operation
  Fix for feliperazeek#36 (Class references not cleaned up on hot reload)
  Fix for feliperazeek#38 (@onetomany causes "Type not allowed" exception)
  Fix for feliperazeek#34 (cannot parse indexed date on record retrieval)
  Upgrade to ES 0.18.5
  Fix for feliperazeek#37 (do not index @transient fields)
  Fixed elasticSearch tag path (fixes bug in _at least_ 1.2.4-RC3)
  Fixed route indentation to make file more readable
  Add support for Float conversion to ReflectionUtil
  Releasing 0.3
  setQuery(QueryBuilder) is available from es-0.17.0 (See ES issue 994)
  Log type mapping
  ...

Conflicts:
	conf/routes
  • Loading branch information
iskra-vitaly committed Mar 6, 2012
2 parents 2296f57 + 1b94cb6 commit 5a05723
Show file tree
Hide file tree
Showing 36 changed files with 2,583 additions and 555 deletions.
4 changes: 2 additions & 2 deletions app/controllers/elasticsearch/ElasticSearchController.java
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,9 @@ public Long count(String search, String searchFields, String where) {
* @return the list
*/
@SuppressWarnings("unchecked")
public SearchResults<Model> findPage(int page, String search, String searchFields, String orderBy, String order, String where) {
public <M extends Model> SearchResults<M> findPage(int page, String search, String searchFields, String orderBy, String order, String where) {
BoolQueryBuilder qb = buildQueryBuilder(search, searchFields, where);
Query<Model> query = ElasticSearch.query(qb, entityClass);
Query<M> query = (Query<M>) ElasticSearch.query(qb, entityClass);
// FIXME Currently we ignore the orderBy and order fields
query.from((page - 1) * getPageSize()).size(getPageSize());
query.hydrate(true);
Expand Down
2 changes: 0 additions & 2 deletions conf/application.conf.debug
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,3 @@ application.log.system.out=on
play.jobs.pool=50


elasticsearch.delivery=rabbitmq
elasticsearch.rabbitmq.queue=elasticsearch
4 changes: 2 additions & 2 deletions conf/dependencies.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
self: play -> elasticsearch 0.3
self: play -> elasticsearch 0.5

# Application dependencies

require:
- play
- play -> crud
- org.elasticsearch -> elasticsearch 0.17.6
- org.elasticsearch -> elasticsearch 0.18.5
- se.scalablesolutions.akka -> akka-amqp 1.1.2


Expand Down
20 changes: 10 additions & 10 deletions conf/routes
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# This file defines all module routes (Higher priority routes first)
#
# import these routes in the main app as :
# import these routes in the main app as:
# * / module:elasticsearch
#
# ~~~~

GET /? elasticsearch.ElasticSearchAdmin.index
GET /? elasticsearch.ElasticSearchAdmin.index

* /admin/ module:crud
GET /public/ staticDir:public
* /admin/ module:crud
GET /public staticDir:public

#{elasticSearch.types}
GET /? ${type.controllerClass.name.substring(12).replace('$','')}.index
GET /${type.controllerName}/search ${type.controllerClass.name.substring(12).replace('$','')}.search
POST /${type.controllerName}/search ${type.controllerClass.name.substring(12).replace('$','')}.search
GET /? ${type.controllerClass.name.substring(12).replace('$','')}.index
GET /${type.controllerName}/search ${type.controllerClass.name.substring(12).replace('$','')}.search
POST /${type.controllerName}/search ${type.controllerClass.name.substring(12).replace('$','')}.search
#{/elasticSearch.types}


GET /es-admin elasticsearch.ElasticSearchAdmin.index
GET /es-admin/ elasticsearch.ElasticSearchAdmin.index
GET /es-admin elasticsearch.ElasticSearchAdmin.index
GET /es-admin/ elasticsearch.ElasticSearchAdmin.index

* /{controller}/{action} {controller}.{action}
* /{controller}/{action} {controller}.{action}
40 changes: 24 additions & 16 deletions src/play/modules/elasticsearch/ElasticSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,16 @@
*/
package play.modules.elasticsearch;

import play.modules.elasticsearch.adapter.ElasticSearchAdapter;
import play.modules.elasticsearch.search.SearchResults;
import play.modules.elasticsearch.transformer.JPATransformer;
import play.modules.elasticsearch.transformer.Transformer;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.action.search.SearchRequestBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.facet.AbstractFacetBuilder;

import play.Logger;
import play.Play;
import play.db.Model;
import play.modules.elasticsearch.mapping.ModelMapper;
import play.modules.elasticsearch.search.SearchResults;

/**
* The Class ElasticSearch.
Expand All @@ -45,8 +40,7 @@ public abstract class ElasticSearch {
* @return the client
*/
public static Client client() {
ElasticSearchPlugin plugin = Play.plugin(ElasticSearchPlugin.class);
return plugin.client();
return ElasticSearchPlugin.client();
}

/**
Expand All @@ -62,7 +56,8 @@ public static Client client() {
* @return the search request builder
*/
static <T extends Model> SearchRequestBuilder builder(QueryBuilder query, Class<T> clazz) {
String index = ElasticSearchAdapter.getIndexName(clazz);
ModelMapper<T> mapper = ElasticSearchPlugin.getMapper(clazz);
String index = mapper.getIndexName();
SearchRequestBuilder builder = client().prepareSearch(index).setSearchType(SearchType.QUERY_THEN_FETCH).setQuery(query);
return builder;
}
Expand All @@ -79,8 +74,8 @@ static <T extends Model> SearchRequestBuilder builder(QueryBuilder query, Class<
*
* @return the query
*/
public static <T extends Model> Query query(QueryBuilder query, Class<T> clazz) {
return new Query(clazz, query);
public static <T extends Model> Query<T> query(QueryBuilder query, Class<T> clazz) {
return new Query<T>(clazz, query);
}

/**
Expand All @@ -97,7 +92,7 @@ public static <T extends Model> Query query(QueryBuilder query, Class<T> clazz)
*
* @return the search results
*/
public static <T extends Model> SearchResults search(QueryBuilder query, Class<T> clazz, AbstractFacetBuilder... facets) {
public static <T extends Model> SearchResults<T> search(QueryBuilder query, Class<T> clazz, AbstractFacetBuilder... facets) {
return search(query, clazz, false, facets);
}

Expand All @@ -115,7 +110,7 @@ public static <T extends Model> SearchResults search(QueryBuilder query, Class<T
*
* @return the search results
*/
public static <T extends Model> SearchResults searchAndHydrate(QueryBuilder queryBuilder, Class<T> clazz, AbstractFacetBuilder... facets) {
public static <T extends Model> SearchResults<T> searchAndHydrate(QueryBuilder queryBuilder, Class<T> clazz, AbstractFacetBuilder... facets) {
return search(queryBuilder, clazz, true, facets);
}

Expand All @@ -135,9 +130,9 @@ public static <T extends Model> SearchResults searchAndHydrate(QueryBuilder quer
*
* @return the search results
*/
private static <T extends Model> SearchResults search(QueryBuilder query, Class<T> clazz, boolean hydrate, AbstractFacetBuilder... facets) {
private static <T extends Model> SearchResults<T> search(QueryBuilder query, Class<T> clazz, boolean hydrate, AbstractFacetBuilder... facets) {
// Build a query for this search request
Query search = query(query, clazz);
Query<T> search = query(query, clazz);

// Control hydration
search.hydrate(hydrate);
Expand All @@ -149,5 +144,18 @@ private static <T extends Model> SearchResults search(QueryBuilder query, Class<

return search.fetch();
}

/**
* Indexes the given model
*
* @param <T>
* the model type
* @param model
* the model
*/
public static <T extends Model> void index(T model) {
ElasticSearchPlugin plugin = Play.plugin(ElasticSearchPlugin.class);
plugin.index(model);
}

}
25 changes: 17 additions & 8 deletions src/play/modules/elasticsearch/ElasticSearchIndexAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
*/
package play.modules.elasticsearch;

import org.elasticsearch.client.Client;

import play.Logger;
import play.db.Model;
import play.modules.elasticsearch.adapter.ElasticSearchAdapter;
import play.modules.elasticsearch.mapping.ModelMapper;
import play.modules.elasticsearch.util.ExceptionUtil;
import play.Logger;

/**
* The Class ElasticSearchIndexAction.
Expand All @@ -37,15 +41,20 @@ public void invoke(ElasticSearchIndexEvent message) {
// Log Debug
Logger.info("Elastic Search - %s Event", message);

Client client = ElasticSearchPlugin.client();
Model object = message.getObject();
@SuppressWarnings("unchecked")
ModelMapper<Model> mapper = (ModelMapper<Model>) ElasticSearchPlugin.getMapper(object.getClass());

// Index Event
try {
switch(message.getType()) {
case INDEX:
ElasticSearchAdapter.indexModel(ElasticSearchPlugin.client(), message.getObject());
break;
case DELETE:
ElasticSearchAdapter.deleteModel(ElasticSearchPlugin.client(), message.getObject());
break;
switch (message.getType()) {
case INDEX:
ElasticSearchAdapter.indexModel(client, mapper, object);
break;
case DELETE:
ElasticSearchAdapter.deleteModel(client, mapper, object);
break;
}
} catch (Throwable t) {
Logger.error(ExceptionUtil.getStackTrace(t));
Expand Down
3 changes: 1 addition & 2 deletions src/play/modules/elasticsearch/ElasticSearchIndexer.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@
*/
package play.modules.elasticsearch;

import play.modules.elasticsearch.util.ExceptionUtil;
import play.Logger;
import play.db.jpa.NoTransaction;
import play.jobs.Job;
import play.jobs.OnApplicationStart;
import play.libs.F.Promise;
import play.modules.elasticsearch.util.ExceptionUtil;

/**
* Indexer job.
Expand Down
105 changes: 63 additions & 42 deletions src/play/modules/elasticsearch/ElasticSearchPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@

import static org.elasticsearch.node.NodeBuilder.nodeBuilder;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.elasticsearch.client.Client;
Expand All @@ -37,8 +38,13 @@
import play.Play;
import play.PlayPlugin;
import play.db.Model;
import play.modules.elasticsearch.ElasticSearchIndexEvent.Type;
import play.modules.elasticsearch.adapter.ElasticSearchAdapter;
import play.modules.elasticsearch.mapping.MapperFactory;
import play.modules.elasticsearch.mapping.MappingUtil;
import play.modules.elasticsearch.mapping.ModelMapper;
import play.modules.elasticsearch.util.ExceptionUtil;
import play.modules.elasticsearch.util.ReflectionUtil;
import play.mvc.Router;

// TODO: Auto-generated Javadoc
Expand All @@ -50,8 +56,11 @@ public class ElasticSearchPlugin extends PlayPlugin {
/** The started. */
private static boolean started = false;

/** The model index. */
private static Map<Class<?>, Boolean> modelIndex = null;
/** The mappers index. */
private static Map<Class<?>, ModelMapper<?>> mappers = null;

/** The started indices. */
private static Set<Class<?>> indicesStarted = null;

/** The client. */
private static Client client = null;
Expand Down Expand Up @@ -123,8 +132,10 @@ public static ElasticSearchDeliveryMode getDeliveryMode() {
*/
@Override
public void onApplicationStart() {
// Start Model Map
modelIndex = new HashMap<Class<?>, Boolean>();
// (re-)set caches
mappers = new HashMap<Class<?>, ModelMapper<?>>();
indicesStarted = new HashSet<Class<?>>();
ReflectionUtil.clearCache();

// Make sure it doesn't get started more than once
if ((client != null) || started) {
Expand Down Expand Up @@ -175,28 +186,30 @@ public void onApplicationStart() {
throw new RuntimeException("Elastic Search Client cannot be null - please check the configuration provided and the health of your Elastic Search instances.");
}
}

/**
* Checks if is elastic searchable.
*
* @param o
* the o
* @return true, if is elastic searchable
*/
private boolean isElasticSearchable(Object o) {
Class<?> clazz = o.getClass();
while (clazz != null) {
// Logger.info("Class: %s", clazz);
for (Annotation a : clazz.getAnnotations()) {
// Logger.info("Class: %s - Annotation: %s", clazz,
// a.toString());
if (a.toString().indexOf("ElasticSearchable") > -1) {
return true;
}
}
clazz = clazz.getSuperclass();

@SuppressWarnings("unchecked")
public static <M> ModelMapper<M> getMapper(Class<M> clazz) {
if (mappers.containsKey(clazz)) {
return (ModelMapper<M>) mappers.get(clazz);
}

ModelMapper<M> mapper = MapperFactory.getMapper(clazz);
mappers.put(clazz, mapper);

return mapper;
}

private static void startIndexIfNeeded(Class<Model> clazz) {
if (!indicesStarted.contains(clazz)) {
ModelMapper<Model> mapper = getMapper(clazz);
Logger.info("Start Index for Class: %s", clazz);
ElasticSearchAdapter.startIndex(client(), mapper);
indicesStarted.add(clazz);
}
return false;
}

private static boolean isInterestingEvent(String event) {
return event.endsWith(".objectPersisted") || event.endsWith(".objectUpdated") || event.endsWith(".objectDeleted");
}

/**
Expand All @@ -209,33 +222,24 @@ public void onEvent(String message, Object context) {
// Log Debug
Logger.info("Received %s Event, Object: %s", message, context);

if (!message.endsWith(".objectPersisted") && !message.endsWith(".objectUpdated") && !message.endsWith(".objectDeleted")) {
if (isInterestingEvent(message) == false) {
return;
}

Logger.debug("Processing %s Event", message);

// Check if object has annotation
boolean isSearchable = this.isElasticSearchable(context);
// Logger.info("Searchable: %s", isSearchable);
if (isSearchable == false) {
// Logger.debug("Not marked to be elastic searchable!");
// Check if object is searchable
if (MappingUtil.isSearchable(context.getClass()) == false) {
return;
}

// Get Plugin
ElasticSearchPlugin plugin = Play.plugin(ElasticSearchPlugin.class);

// Sanity check, we only index models
Validate.isTrue(context instanceof Model, "Only play.db.Model subclasses can be indexed");

// Check if the index has been started

// Start index if needed
@SuppressWarnings("unchecked")
Class<Model> clazz = (Class<Model>) context.getClass();
if (modelIndex.containsKey(clazz) == false) {
Logger.info("Start Index for Class: %s", clazz);
ElasticSearchAdapter.startIndex(plugin.client(), clazz);
modelIndex.put(clazz, Boolean.TRUE);
}
startIndexIfNeeded(clazz);

// Define Event
ElasticSearchIndexEvent event = null;
Expand All @@ -256,5 +260,22 @@ public void onEvent(String message, Object context) {
handler.handle(event);
}
}

<M extends Model> void index(M model) {
@SuppressWarnings("unchecked")
Class<Model> clazz = (Class<Model>) model.getClass();

// Check if object is searchable
if (MappingUtil.isSearchable(clazz) == false) {
throw new IllegalArgumentException("model is not searchable");
}

startIndexIfNeeded(clazz);

ElasticSearchIndexEvent event = new ElasticSearchIndexEvent(model, Type.INDEX);
ElasticSearchDeliveryMode deliveryMode = getDeliveryMode();
IndexEventHandler handler = deliveryMode.getHandler();
handler.handle(event);
}

}
Loading

0 comments on commit 5a05723

Please sign in to comment.