Fix some minor things in function score parser/builder

- remove default scale weight in builder
- make parameters object/double instead of string
- do not convert number to string and back again, parse double instead
- remove javadoc reference to test classes
- Set parameters in constructor instead of in method
This commit is contained in:
Britta Weber 2013-08-14 12:57:03 +02:00
parent 592e637293
commit ebbd00acc2
7 changed files with 73 additions and 93 deletions

View File

@ -19,7 +19,6 @@
package org.elasticsearch.index.query.functionscore;
import org.elasticsearch.ElasticSearchIllegalStateException;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -30,45 +29,37 @@ public abstract class DecayFunctionBuilder implements ScoreFunctionBuilder {
protected static final String REFERNECE = "reference";
protected static final String SCALE = "scale";
protected static final String SCALE_WEIGHT = "scale_weight";
protected static final String SCALE_DEFAULT = "0.5";
private String fieldName;
private String reference;
private String scale;
private String scaleWeight;
public void setParameters(String fieldName, String reference, String scale, String scaleWeight) {
if(this.fieldName != null ) {
throw new ElasticSearchIllegalStateException("Can not set parameters of decay function more than once.");
}
private String fieldName;
private Object reference;
private Object scale;
private double scaleWeight = -1;
public DecayFunctionBuilder(String fieldName, Object reference, Object scale) {
this.fieldName = fieldName;
this.reference = reference;
this.scale = scale;
}
public DecayFunctionBuilder setScaleWeight(double scaleWeight) {
if(scaleWeight <=0 || scaleWeight >= 1.0) {
throw new ElasticSearchIllegalStateException("scale weight parameter must be in range 0..1!");
}
this.scaleWeight = scaleWeight;
return this;
}
public void setParameters(String fieldName, String reference, String scale) {
setParameters(fieldName, reference, scale, SCALE_DEFAULT);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(getName());
builder.startObject(fieldName);
builder.field(REFERNECE, reference);
builder.field(SCALE, scale);
builder.startObject(fieldName);
builder.field(REFERNECE, reference);
builder.field(SCALE, scale);
if (scaleWeight > 0) {
builder.field(SCALE_WEIGHT, scaleWeight);
builder.endObject();
}
builder.endObject();
builder.endObject();
return builder;
}
public void addGeoParams(String fieldName, double lat, double lon, String scale) {
addGeoParams(fieldName, lat, lon, scale, SCALE_DEFAULT);
}
public void addGeoParams(String fieldName, double lat, double lon, String scale, String scaleWeight) {
String geoLoc = Double.toString(lat) + ", " + Double.toString(lon);
setParameters(fieldName, geoLoc, scale, scaleWeight);
}
}

View File

@ -84,12 +84,7 @@ import java.io.IOException;
* See {@link GaussDecayFunctionBuilder} and {@link GaussDecayFunctionParser}
* for an example. The parser furthermore needs to be registered in the
* {@link org.elasticsearch.index.query.functionscore.FunctionScoreModule
* FunctionScoreModule}. See
* {@link org.elasticsearch.test.integration.search.functionscore.CustomDistanceScorePlugin
* CustomDistanceScorePlugin} and
* {@link org.elasticsearch.test.integration.search.functionscore.CustomDistanceScorePlugin
* DistanceScorePluginTest DistanceScorePluginTest} for an example on how to
* write your own function and plugin.
* FunctionScoreModule}.
*
* **/
@ -165,28 +160,30 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
NumberFieldMapper<?> mapper) throws IOException {
XContentParser.Token token;
String parameterName = null;
String scaleString = null;
String referenceString = null;
double scale = 0;
double reference = 0;
double scaleWeight = 0.5;
boolean scaleFound = false;
boolean refFound = false;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
parameterName = parser.currentName();
} else if (parameterName.equals(DecayFunctionBuilder.SCALE)) {
scaleString = parser.text();
scale = parser.doubleValue();
scaleFound = true;
} else if (parameterName.equals(DecayFunctionBuilder.SCALE_WEIGHT)) {
scaleWeight = parser.doubleValue();
} else if (parameterName.equals(DecayFunctionBuilder.REFERNECE)) {
referenceString = parser.text();
reference = parser.doubleValue();
refFound = true;
} else {
throw new ElasticSearchParseException("Parameter " + parameterName + " not supported!");
}
}
if (scaleString == null || referenceString == null) {
if (!scaleFound || !refFound) {
throw new ElasticSearchParseException("Both " + DecayFunctionBuilder.SCALE + "and " + DecayFunctionBuilder.REFERNECE
+ " must be set for numeric fields.");
}
double reference = mapper.value(referenceString).doubleValue();
double scale = mapper.value(scaleString).doubleValue();
IndexNumericFieldData<?> numericFieldData = parseContext.fieldData().getForField(mapper);
return new NumericFieldDataScoreFunction(reference, scale, scaleWeight, getDecayFunction(), numericFieldData);
}
@ -375,7 +372,7 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
@Override
public Explanation explainScore(int docId, Explanation subQueryExpl) {
ComplexExplanation ce = new ComplexExplanation();
ce.setValue((float)score(docId, subQueryExpl.getValue()));
ce.setValue((float) score(docId, subQueryExpl.getValue()));
ce.setMatch(true);
ce.setDescription("subQueryScore * Function for field " + getFieldName() + ":");
ce.addDetail(func.explainFunction(getDistanceString(docId), distance(docId), scale));
@ -385,7 +382,7 @@ public abstract class DecayFunctionParser implements ScoreFunctionParser {
@Override
public Explanation explainFactor(int docId) {
ComplexExplanation ce = new ComplexExplanation();
ce.setValue((float)factor(docId));
ce.setValue((float) factor(docId));
ce.setMatch(true);
ce.setDescription("subQueryScore * Function for field " + getFieldName() + ":");
ce.addDetail(func.explainFunction(getDistanceString(docId), distance(docId), scale));

View File

@ -24,6 +24,10 @@ import org.elasticsearch.index.query.functionscore.DecayFunctionBuilder;
public class ExponentialDecayFunctionBuilder extends DecayFunctionBuilder {
public ExponentialDecayFunctionBuilder(String fieldName, Object reference, Object scale) {
super(fieldName, reference, scale);
}
@Override
public String getName() {
return ExponentialDecayFunctionParser.NAMES[0];

View File

@ -24,6 +24,10 @@ import org.elasticsearch.index.query.functionscore.DecayFunctionBuilder;
public class GaussDecayFunctionBuilder extends DecayFunctionBuilder {
public GaussDecayFunctionBuilder(String fieldName, Object reference, Object scale) {
super(fieldName, reference, scale);
}
@Override
public String getName() {
return GaussDecayFunctionParser.NAMES[0];

View File

@ -23,6 +23,10 @@ import org.elasticsearch.index.query.functionscore.DecayFunctionBuilder;
public class LinearDecayFunctionBuilder extends DecayFunctionBuilder {
public LinearDecayFunctionBuilder(String fieldName, Object reference, Object scale) {
super(fieldName, reference, scale);
}
@Override
public String getName() {
return LinearDecayFunctionParser.NAMES[0];

View File

@ -19,6 +19,7 @@
package org.elasticsearch.test.integration.search.functionscore;
import org.elasticsearch.ElasticSearchIllegalStateException;
import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
@ -86,8 +87,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
refresh();
// Test Gauss
DecayFunctionBuilder fb = new GaussDecayFunctionBuilder();
fb.addGeoParams("loc", 11, 20, "1000km");
List<Float> lonlat = new ArrayList<Float>();
lonlat.add(new Float(20));
lonlat.add(new Float(11));
DecayFunctionBuilder fb = new GaussDecayFunctionBuilder("loc", lonlat, "1000km");
ActionFuture<SearchResponse> response = client().search(
searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
@ -106,8 +109,7 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
assertThat(sh.getAt(0).getId(), equalTo("1"));
assertThat(sh.getAt(1).getId(), equalTo("2"));
// Test Exp
fb = new ExponentialDecayFunctionBuilder();
fb.addGeoParams("loc", 11, 20, "1000km");
fb = new ExponentialDecayFunctionBuilder("loc", lonlat, "1000km");
response = client().search(
searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
@ -126,8 +128,7 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
assertThat(sh.getAt(0).getId(), equalTo("1"));
assertThat(sh.getAt(1).getId(), equalTo("2"));
// Test Lin
fb = new LinearDecayFunctionBuilder();
fb.addGeoParams("loc", 11, 20, "1000km");
fb = new LinearDecayFunctionBuilder("loc", lonlat, "1000km");
response = client().search(
searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
@ -160,8 +161,7 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
.source(jsonBuilder().startObject().field("test", "value").field("num1", "2013-05-28").endObject())).actionGet();
refresh();
DecayFunctionBuilder gfb = new GaussDecayFunctionBuilder();
gfb.setParameters("num1", "2013-05-28", "-1d");
DecayFunctionBuilder gfb = new GaussDecayFunctionBuilder("num1", "2013-05-28", "-1d");
ActionFuture<SearchResponse> response = client().search(
searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
@ -176,32 +176,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
}
@Test(expected = SearchPhaseExecutionException.class)
@Test(expected = ElasticSearchIllegalStateException.class)
public void testExceptionThrownIfScaleRefNotBetween0And1() throws Exception {
createIndexMapped("test", "type1", "test", "string", "num1", "date");
ensureYellow();
client().index(
indexRequest("test").type("type1").id("1")
.source(jsonBuilder().startObject().field("test", "value").field("num1", "2013-05-27").endObject())).actionGet();
client().index(
indexRequest("test").type("type1").id("2")
.source(jsonBuilder().startObject().field("test", "value").field("num1", "2013-05-28").endObject())).actionGet();
refresh();
DecayFunctionBuilder gfb = new GaussDecayFunctionBuilder();
gfb.setParameters("num1", "2013-05-28", "1d", "-1");
ActionFuture<SearchResponse> response = client().search(
searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
searchSource().explain(true).query(functionScoreQuery(termQuery("test", "value")).add(gfb))));
SearchResponse sr = response.actionGet();
ElasticsearchAssertions.assertNoFailures(sr);
SearchHits sh = sr.getHits();
assertThat(sh.hits().length, equalTo(2));
assertThat(sh.getAt(0).getId(), equalTo("2"));
assertThat(sh.getAt(1).getId(), equalTo("1"));
DecayFunctionBuilder gfb = new GaussDecayFunctionBuilder("num1", "2013-05-28", "1d").setScaleWeight(100);
}
@ -231,10 +209,8 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
refresh();
DecayFunctionBuilder gfb1 = new LinearDecayFunctionBuilder();
gfb1.setParameters("num1", "2013-05-28", "+3d");
DecayFunctionBuilder gfb2 = new LinearDecayFunctionBuilder();
gfb2.setParameters("num2", "0.0", "1");
DecayFunctionBuilder gfb1 = new LinearDecayFunctionBuilder("num1", "2013-05-28", "+3d");
DecayFunctionBuilder gfb2 = new LinearDecayFunctionBuilder("num2", "0.0", "1");
ActionFuture<SearchResponse> response = client().search(
searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
@ -282,13 +258,13 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
indexRandom("test", false, builders);
refresh();
DecayFunctionBuilder gfb1 = new LinearDecayFunctionBuilder();
DecayFunctionBuilder gfb2 = new LinearDecayFunctionBuilder();
DecayFunctionBuilder gfb3 = new LinearDecayFunctionBuilder();
gfb1.setParameters("date", "2013-05-30", "+15d");
gfb2.addGeoParams("geo", 110, 100, "1000km");
gfb3.setParameters("num", Integer.toString(numDocs), Integer.toString(numDocs / 2));
List<Float> lonlat = new ArrayList<Float>();
lonlat.add(new Float(100));
lonlat.add(new Float(110));
DecayFunctionBuilder gfb1 = new LinearDecayFunctionBuilder("date", "2013-05-30", "+15d");
DecayFunctionBuilder gfb2 = new LinearDecayFunctionBuilder("geo", lonlat, "1000km");
DecayFunctionBuilder gfb3 = new LinearDecayFunctionBuilder("num", Integer.toString(numDocs), Integer.toString(numDocs / 2));
ActionFuture<SearchResponse> response = client().search(
searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
@ -324,8 +300,10 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
jsonBuilder().startObject().field("test", "value").startObject("geo").field("lat", 1).field("lon", 2).endObject()
.endObject())).actionGet();
refresh();
DecayFunctionBuilder gfb2 = new LinearDecayFunctionBuilder();
gfb2.addGeoParams("type1.geo", 110, 100, "1000km");
List<Float> lonlat = new ArrayList<Float>();
lonlat.add(new Float(100));
lonlat.add(new Float(110));
DecayFunctionBuilder gfb2 = new LinearDecayFunctionBuilder("type1.geo", lonlat, "1000km");
ActionFuture<SearchResponse> response = client().search(
searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
searchSource()
@ -345,9 +323,8 @@ public class DecayFunctionScoreTests extends AbstractSharedClusterTest {
indexRequest("test").type("type").source(
jsonBuilder().startObject().field("test", "value").field("num", Integer.toString(1)).endObject())).actionGet();
refresh();
DecayFunctionBuilder lfb = new LinearDecayFunctionBuilder();
//so, we indexed a string field, but now we try to score a num field
lfb.setParameters("num", Integer.toString(1), Integer.toString(1 / 2));
DecayFunctionBuilder lfb = new LinearDecayFunctionBuilder("num", Integer.toString(1), Integer.toString(1 / 2));
// so, we indexed a string field, but now we try to score a num field
ActionFuture<SearchResponse> response = client()
.search(searchRequest()
.searchType(SearchType.QUERY_THEN_FETCH)

View File

@ -83,8 +83,7 @@ public class FunctionScorePluginTests extends AbstractNodesTests {
.source(jsonBuilder().startObject().field("test", "value").field("num1", "2013-05-27").endObject())).actionGet();
client.admin().indices().prepareRefresh().execute().actionGet();
DecayFunctionBuilder gfb = new CustomDistanceScoreBuilder();
gfb.setParameters("num1", "2013-05-28", "+1d");
DecayFunctionBuilder gfb = new CustomDistanceScoreBuilder("num1", "2013-05-28", "+1d");
ActionFuture<SearchResponse> response = client.search(searchRequest().searchType(SearchType.QUERY_THEN_FETCH).source(
searchSource().explain(false).query(functionScoreQuery(termQuery("test", "value")).add(gfb))));
@ -160,6 +159,10 @@ public class FunctionScorePluginTests extends AbstractNodesTests {
public class CustomDistanceScoreBuilder extends DecayFunctionBuilder {
public CustomDistanceScoreBuilder(String fieldName, Object reference, Object scale) {
super(fieldName, reference, scale);
}
@Override
public String getName() {
return CustomDistanceScoreParser.NAMES[0];