Skip to content

Commit

Permalink
HSEARCH-2603 Use the painless scripting language with Elasticsearch 5+
Browse files Browse the repository at this point in the history
Because groovy has been deprecated, because painless doesn't require
any server-side configuration, and because only painless is supported on
Amazon Web Services.
  • Loading branch information
yrodiere authored and Sanne committed May 30, 2017
1 parent 9ba3111 commit b3d6dae
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 19 deletions.
Expand Up @@ -7,6 +7,7 @@
package org.hibernate.search.elasticsearch.dialect.impl;

import org.hibernate.search.elasticsearch.gson.impl.GsonProvider;
import org.hibernate.search.elasticsearch.query.impl.ElasticsearchQueryFactory;
import org.hibernate.search.elasticsearch.schema.impl.ElasticsearchSchemaAccessor;
import org.hibernate.search.elasticsearch.schema.impl.ElasticsearchSchemaTranslator;
import org.hibernate.search.elasticsearch.schema.impl.ElasticsearchSchemaValidator;
Expand All @@ -31,4 +32,6 @@ public interface ElasticsearchDialect {

MissingValueStrategy createMissingValueStrategy();

ElasticsearchQueryFactory createQueryFactory();

}
Expand Up @@ -10,6 +10,8 @@
import org.hibernate.search.elasticsearch.gson.impl.DefaultGsonProvider;
import org.hibernate.search.elasticsearch.gson.impl.GsonProvider;
import org.hibernate.search.elasticsearch.nulls.impl.Elasticsearch2MissingValueStrategy;
import org.hibernate.search.elasticsearch.query.impl.Elasticsearch2QueryFactory;
import org.hibernate.search.elasticsearch.query.impl.ElasticsearchQueryFactory;
import org.hibernate.search.elasticsearch.schema.impl.Elasticsearch2SchemaTranslator;
import org.hibernate.search.elasticsearch.schema.impl.Elasticsearch2SchemaValidator;
import org.hibernate.search.elasticsearch.schema.impl.ElasticsearchSchemaAccessor;
Expand Down Expand Up @@ -62,4 +64,9 @@ public MissingValueStrategy createMissingValueStrategy() {
return Elasticsearch2MissingValueStrategy.INSTANCE;
}

@Override
public ElasticsearchQueryFactory createQueryFactory() {
return new Elasticsearch2QueryFactory();
}

}
Expand Up @@ -10,6 +10,8 @@
import org.hibernate.search.elasticsearch.gson.impl.DefaultGsonProvider;
import org.hibernate.search.elasticsearch.gson.impl.GsonProvider;
import org.hibernate.search.elasticsearch.nulls.impl.Elasticsearch5MissingValueStrategy;
import org.hibernate.search.elasticsearch.query.impl.Elasticsearch5QueryFactory;
import org.hibernate.search.elasticsearch.query.impl.ElasticsearchQueryFactory;
import org.hibernate.search.elasticsearch.schema.impl.Elasticsearch5SchemaTranslator;
import org.hibernate.search.elasticsearch.schema.impl.Elasticsearch5SchemaValidator;
import org.hibernate.search.elasticsearch.schema.impl.ElasticsearchSchemaAccessor;
Expand Down Expand Up @@ -62,4 +64,9 @@ public MissingValueStrategy createMissingValueStrategy() {
return Elasticsearch5MissingValueStrategy.INSTANCE;
}

@Override
public ElasticsearchQueryFactory createQueryFactory() {
return new Elasticsearch5QueryFactory();
}

}
Expand Up @@ -17,6 +17,7 @@
import org.hibernate.search.elasticsearch.dialect.impl.ElasticsearchDialectFactory;
import org.hibernate.search.elasticsearch.gson.impl.GsonProvider;
import org.hibernate.search.elasticsearch.processor.impl.ElasticsearchWorkProcessor;
import org.hibernate.search.elasticsearch.query.impl.ElasticsearchQueryFactory;
import org.hibernate.search.elasticsearch.schema.impl.DefaultElasticsearchSchemaCreator;
import org.hibernate.search.elasticsearch.schema.impl.DefaultElasticsearchSchemaDropper;
import org.hibernate.search.elasticsearch.schema.impl.DefaultElasticsearchSchemaMigrator;
Expand Down Expand Up @@ -52,8 +53,6 @@ public class DefaultElasticsearchService implements ElasticsearchService, Starta

private static final String QUERY_PROPERTIES_PREFIX = "hibernate.search.";

private ElasticsearchQueryOptions queryOptions;

private ElasticsearchClient client;

private GsonProvider gsonProvider;
Expand All @@ -74,6 +73,10 @@ public class DefaultElasticsearchService implements ElasticsearchService, Starta

private MissingValueStrategy missingValueStrategy;

private ElasticsearchQueryFactory queryFactory;

private ElasticsearchQueryOptions queryOptions;

@Override
public void start(Properties properties, BuildContext context) {
ServiceManager serviceManager = context.getServiceManager();
Expand Down Expand Up @@ -108,6 +111,8 @@ public void start(Properties properties, BuildContext context) {
this.schemaMigrator = new DefaultElasticsearchSchemaMigrator( schemaAccessor, schemaValidator );

this.missingValueStrategy = dialect.createMissingValueStrategy();

this.queryFactory = dialect.createQueryFactory();
}
}

Expand Down Expand Up @@ -172,6 +177,11 @@ public MissingValueStrategy getMissingValueStrategy() {
return missingValueStrategy;
}

@Override
public ElasticsearchQueryFactory getQueryFactory() {
return queryFactory;
}

@Override
public ElasticsearchQueryOptions getQueryOptions() {
return queryOptions;
Expand Down
Expand Up @@ -657,15 +657,10 @@ private void addScriptFields(JsonBuilder.Object payloadBuilder) {
// the results. If we don't sort by distance, we need to request for the distance using a script_field.
payloadBuilder.add( "script_fields",
JsonBuilder.object().add( SPATIAL_DISTANCE_FIELD, JsonBuilder.object()
.add( "script", JsonBuilder.object()
.add( "params",
JsonBuilder.object()
.addProperty( "lat", spatialSearchCenter.getLatitude() )
.addProperty( "lon", spatialSearchCenter.getLongitude() )
)
// We multiply by 0.001 to Convert from meters to kilmeters
.addProperty( "inline", "doc['" + spatialFieldName + "'] ? doc['" + spatialFieldName + "'].arcDistance(lat,lon)*0.001 : null" )
.addProperty( "lang", "groovy" )
.add(
"script",
elasticsearchService.getQueryFactory()
.createSpatialDistanceScript( spatialSearchCenter, spatialFieldName )
)
)
);
Expand Down
Expand Up @@ -8,6 +8,7 @@

import org.hibernate.search.elasticsearch.gson.impl.GsonProvider;
import org.hibernate.search.elasticsearch.processor.impl.ElasticsearchWorkProcessor;
import org.hibernate.search.elasticsearch.query.impl.ElasticsearchQueryFactory;
import org.hibernate.search.elasticsearch.schema.impl.ElasticsearchSchemaCreator;
import org.hibernate.search.elasticsearch.schema.impl.ElasticsearchSchemaDropper;
import org.hibernate.search.elasticsearch.schema.impl.ElasticsearchSchemaMigrator;
Expand Down Expand Up @@ -41,6 +42,8 @@ public interface ElasticsearchService extends Service {

MissingValueStrategy getMissingValueStrategy();

ElasticsearchQueryFactory getQueryFactory();

ElasticsearchQueryOptions getQueryOptions();

}
@@ -0,0 +1,37 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.elasticsearch.query.impl;

import org.hibernate.search.elasticsearch.impl.JsonBuilder;
import org.hibernate.search.spatial.Coordinates;

import com.google.gson.JsonObject;

/**
* @author Yoann Rodiere
*/
public class Elasticsearch2QueryFactory implements ElasticsearchQueryFactory {

@Override
public JsonObject createSpatialDistanceScript(Coordinates center, String spatialFieldName) {
return JsonBuilder.object()
.add( "params",
JsonBuilder.object()
.addProperty( "lat", center.getLatitude() )
.addProperty( "lon", center.getLongitude() )
)
// We multiply by 0.001 to Convert from meters to kilometers
.addProperty(
"inline",
"doc['" + spatialFieldName + "'] ?"
+ " doc['" + spatialFieldName + "'].arcDistance(lat,lon)*0.001"
+ " : null" )
.addProperty( "lang", "groovy" )
.build();
}

}
@@ -0,0 +1,37 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.elasticsearch.query.impl;

import org.hibernate.search.elasticsearch.impl.JsonBuilder;
import org.hibernate.search.spatial.Coordinates;

import com.google.gson.JsonObject;

/**
* @author Yoann Rodiere
*/
public class Elasticsearch5QueryFactory implements ElasticsearchQueryFactory {

@Override
public JsonObject createSpatialDistanceScript(Coordinates center, String spatialFieldName) {
return JsonBuilder.object()
.add( "params",
JsonBuilder.object()
.addProperty( "lat", center.getLatitude() )
.addProperty( "lon", center.getLongitude() )
)
// We multiply by 0.001 to Convert from meters to kilometers
.addProperty(
"inline",
"doc['" + spatialFieldName + "'].value !== null ?"
+ " doc['" + spatialFieldName + "'].arcDistance(params.lat,params.lon)*0.001"
+ " : null" )
.addProperty( "lang", "painless" )
.build();
}

}
@@ -0,0 +1,27 @@
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.elasticsearch.query.impl;

import org.hibernate.search.spatial.Coordinates;

import com.google.gson.JsonObject;

/**
* An object responsible for creating parts of an Elasticsearch JSON query.
* <p>
* Should eventually be responsible for building the whole JSON query,
* see HSEARCH-2750.
*
* @see <a href="https://hibernate.atlassian.net/browse/HSEARCH-2750">HSEARCH-2750</a>
*
* @author Yoann Rodiere
*/
public interface ElasticsearchQueryFactory {

JsonObject createSpatialDistanceScript(Coordinates center, String spatialFieldName);

}
Expand Up @@ -64,7 +64,3 @@ discovery.zen.minimum_master_nodes: 1
# Disable starting multiple nodes on a single system:
#
node.max_local_storage_nodes: 1
#
# Enable Groovy scripting support for search: useful for spatial queries
#
script.engine.groovy.inline.search: true
Expand Up @@ -64,7 +64,3 @@ discovery.zen.minimum_master_nodes: 1
# Disable starting multiple nodes on a single system:
#
node.max_local_storage_nodes: 1
#
# Enable Groovy scripting support for search: useful for spatial queries
#
script.engine.groovy.inline.search: true

0 comments on commit b3d6dae

Please sign in to comment.