Skip to content
Permalink
Browse files

Replace sorting by distance with scoring by distance (#280)

  • Loading branch information
fsteeg committed Dec 9, 2016
1 parent 581c491 commit 6cf93d84bb88248573b9714d9107151177809740
Showing with 99 additions and 13 deletions.
  1. +17 −8 app/controllers/Application.java
  2. +4 −5 app/controllers/Index.java
  3. +78 −0 app/controllers/Zero.java
@@ -17,6 +17,8 @@
import org.elasticsearch.index.query.GeoPolygonQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.metrics.tophits.TopHitsBuilder;
@@ -308,22 +310,29 @@ private static String buildDistanceQuery(String q, int from, int size,
}

static SearchResponse executeQuery(int from, int size, QueryBuilder query) {
SearchRequestBuilder searchRequest =
Index.CLIENT.prepareSearch(ES_NAME).setTypes(ES_TYPE)//
.setSearchType(SearchType.QUERY_THEN_FETCH).setQuery(query)//
.setFrom(from)//
.setSize(size);
SearchRequestBuilder searchRequest = Index.CLIENT.prepareSearch(ES_NAME)
.setTypes(ES_TYPE).setSearchType(SearchType.QUERY_THEN_FETCH)
.setQuery(preprocess(query)).setFrom(from).setSize(size);
searchRequest = withAggregations(searchRequest, "type.raw",
localizedLabel("classification.label.raw"),
localizedLabel("fundertype.label.raw"),
localizedLabel("collects.extent.label.raw"));
return searchRequest.execute().actionGet();
}

private static QueryBuilder preprocess(QueryBuilder query) {
String position = session("position");
if (position != null) {
Logger.info("Sorting by distance to current position {}", position);
searchRequest.addSort(new GeoDistanceSortBuilder("location.geo")
.points(new GeoPoint(position)));
ScoreFunctionBuilder locationScore = ScoreFunctionBuilders
.linearDecayFunction("location.geo", new GeoPoint(position), "3km")
.setOffset("0km");
return QueryBuilders.functionScoreQuery(query).boostMode("sum")
.add(QueryBuilders.existsQuery("location.geo"), locationScore)
.add(ScoreFunctionBuilders.scriptFunction(new Script("zero")))
.scoreMode("first");
}
return searchRequest.execute().actionGet();
return query;
}

private static SearchRequestBuilder withAggregations(
@@ -60,11 +60,10 @@ public ConfigurableNode(Settings settings,
Application.CONFIG.getString("index.es.port.tcp"))
.put("script.default_lang", "native").build();

private static Node node =
new ConfigurableNode(
nodeBuilder().settings(clientSettings).local(true).getSettings()
.build(),
Arrays.asList(BundlePlugin.class, LocationAggregation.class)).start();
private static Node node = new ConfigurableNode(
nodeBuilder().settings(clientSettings).local(true).getSettings().build(),
Arrays.asList(BundlePlugin.class, LocationAggregation.class, Zero.class))
.start();
/**
* The Elasticsearch client to be used by all parts of the application
*/
@@ -0,0 +1,78 @@
/* Copyright 2016, hbz. Licensed under the Eclipse Public License 1.0 */

package controllers;

import java.util.Map;

import javax.annotation.Nullable;

import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.AbstractSearchScript;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.NativeScriptFactory;
import org.elasticsearch.script.ScriptModule;

/**
* Native script plugin to return 0.
*
* Yes, this seems completely nuts. Let me explain: <br/>
*
* We need a script that simply returns 0 as a workaround for location scoring,
* see: <br/>
*
* https://github.com/elastic/elasticsearch/issues/7788#issuecomment-57196342
* https://github.com/elastic/elasticsearch/issues/18892#issuecomment-226544977
* <br/>
*
* With Groovy scripting this would be straight-forward, but we run in embedded
* mode and use native scripting for security reasons, see: <br/>
*
* https://github.com/hbz/lobid-organisations/commit/acefce9ba980f2f955c79da71e3ccc8068489d56
* https://github.com/hbz/lobid-organisations/commit/1027537db9b26911d7294532d4f1ae44244205ce
* <br/>
*
* So we have a full native script for this very simple functionality.
*
* @author Fabian Steeg (fsteeg)
*
*/
public class Zero extends Plugin {
@Override
public String name() {
return "zero";
}

@Override
public String description() {
return "Native script to return 0";
}

/**
* @param scriptModule The scriptModule to register this script on
*/
public void onModule(ScriptModule scriptModule) {
scriptModule.registerScript(name(), ZeroScriptFactory.class);
}

/** Factory to construct the script. */
public static class ZeroScriptFactory implements NativeScriptFactory {
@Override
public ExecutableScript newScript(@Nullable Map<String, Object> params) {
return new ZeroScript();
}

@Override
public boolean needsScores() {
return false;
}
}

/** The actual script. */
public static class ZeroScript extends AbstractSearchScript {

@Override
public Object run() {
return 0;
}
}
}

0 comments on commit 6cf93d8

Please sign in to comment.
You can’t perform that action at this time.