mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-17 10:25:15 +00:00
ContextSuggester: Adding couple of tests to catch more bugs
A bunch of minor fixes have been included here, especially due to wrongly parsed mappings. Also using assertions resulted in an NPE because they were disabled in the distribution. Closes #5525
This commit is contained in:
parent
f424319f9a
commit
0ff30ade69
219
rest-api-spec/test/suggest/20_context.yaml
Normal file
219
rest-api-spec/test/suggest/20_context.yaml
Normal file
@ -0,0 +1,219 @@
|
||||
# This test creates one huge mapping in the setup
|
||||
# Every test should use its own field to make sure it works
|
||||
|
||||
setup:
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: test
|
||||
body:
|
||||
mappings:
|
||||
test:
|
||||
"properties":
|
||||
"suggest_context":
|
||||
"type" : "completion"
|
||||
"context":
|
||||
"color":
|
||||
"type" : "category"
|
||||
"suggest_context_default_hardcoded":
|
||||
"type" : "completion"
|
||||
"context":
|
||||
"color":
|
||||
"type" : "category"
|
||||
"default" : "red"
|
||||
"suggest_context_default_path":
|
||||
"type" : "completion"
|
||||
"context":
|
||||
"color":
|
||||
"type" : "category"
|
||||
"default" : "red"
|
||||
"path" : "color"
|
||||
"suggest_geo":
|
||||
"type" : "completion"
|
||||
"context":
|
||||
"location":
|
||||
"type" : "geo"
|
||||
|
||||
---
|
||||
"Simple context suggestion should work":
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_context:
|
||||
input: "Hoodie red"
|
||||
context:
|
||||
color: "red"
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 2
|
||||
body:
|
||||
suggest_context:
|
||||
input: "Hoodie blue"
|
||||
context:
|
||||
color: "blue"
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "hoo"
|
||||
completion:
|
||||
field: suggest_context
|
||||
context:
|
||||
color: "red"
|
||||
|
||||
- match: {result.0.options.0.text: "Hoodie red" }
|
||||
|
||||
---
|
||||
"Hardcoded category value should work":
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_context_default_hardcoded:
|
||||
input: "Hoodie red"
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 2
|
||||
body:
|
||||
suggest_context_default_hardcoded:
|
||||
input: "Hoodie blue"
|
||||
context:
|
||||
color: "blue"
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "hoo"
|
||||
completion:
|
||||
field: suggest_context_default_hardcoded
|
||||
context:
|
||||
color: "red"
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 1 }
|
||||
- match: { result.0.options.0.text: "Hoodie red" }
|
||||
|
||||
|
||||
---
|
||||
"Category suggest context default path should work":
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_context_default_path:
|
||||
input: "Hoodie red"
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 2
|
||||
body:
|
||||
suggest_context_default_path:
|
||||
input: "Hoodie blue"
|
||||
color: "blue"
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "hoo"
|
||||
completion:
|
||||
field: suggest_context_default_path
|
||||
context:
|
||||
color: "red"
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 1 }
|
||||
- match: { result.0.options.0.text: "Hoodie red" }
|
||||
|
||||
- do:
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "hoo"
|
||||
completion:
|
||||
field: suggest_context_default_path
|
||||
context:
|
||||
color: "blue"
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 1 }
|
||||
- match: { result.0.options.0.text: "Hoodie blue" }
|
||||
|
||||
|
||||
---
|
||||
"Geo suggest should work":
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 1
|
||||
body:
|
||||
suggest_geo:
|
||||
input: "Hotel Marriot in Amsterdam"
|
||||
context:
|
||||
location:
|
||||
lat : 52.22
|
||||
lon : 4.53
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: test
|
||||
type: test
|
||||
id: 2
|
||||
body:
|
||||
suggest_geo:
|
||||
input: "Hotel Marriot in Berlin"
|
||||
context:
|
||||
location:
|
||||
lat : 53.31
|
||||
lon : 13.24
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
suggest:
|
||||
body:
|
||||
result:
|
||||
text: "hote"
|
||||
completion:
|
||||
field: suggest_geo
|
||||
context:
|
||||
location:
|
||||
lat : 52.22
|
||||
lon : 4.53
|
||||
|
||||
- length: { result: 1 }
|
||||
- length: { result.0.options: 1 }
|
||||
- match: { result.0.options.0.text: "Hotel Marriot in Amsterdam" }
|
||||
|
@ -21,6 +21,7 @@ package org.apache.lucene.analysis;
|
||||
|
||||
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
|
||||
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
@ -96,7 +97,9 @@ public class PrefixAnalyzer extends Analyzer {
|
||||
this.prefixes = prefixes;
|
||||
this.currentPrefix = null;
|
||||
this.separator = separator;
|
||||
assert (prefixes != null && prefixes.iterator().hasNext()) : "one or more prefix needed";
|
||||
if (prefixes == null || !prefixes.iterator().hasNext()) {
|
||||
throw new ElasticsearchIllegalArgumentException("one or more prefixes needed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,7 +33,7 @@ import org.elasticsearch.search.suggest.term.TermSuggestionBuilder;
|
||||
|
||||
/**
|
||||
* Defines how to perform suggesting. This builders allows a number of global options to be specified and
|
||||
* an arbitrary number of {@link org.elasticsearch.search.suggest.SuggestBuilder.TermSuggestionBuilder} instances.
|
||||
* an arbitrary number of {@link org.elasticsearch.search.suggest.term.TermSuggestionBuilder} instances.
|
||||
* <p/>
|
||||
* Suggesting works by suggesting terms that appear in the suggest text that are similar compared to the terms in
|
||||
* provided text. These spelling suggestions are based on several options described in this class.
|
||||
@ -66,7 +66,7 @@ public class SuggestBuilder implements ToXContent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link org.elasticsearch.search.suggest.SuggestBuilder.TermSuggestionBuilder} instance under a user defined name.
|
||||
* Adds an {@link org.elasticsearch.search.suggest.term.TermSuggestionBuilder} instance under a user defined name.
|
||||
* The order in which the <code>Suggestions</code> are added, is the same as in the response.
|
||||
*/
|
||||
public SuggestBuilder addSuggestion(SuggestionBuilder<?> suggestion) {
|
||||
@ -141,17 +141,28 @@ public class SuggestBuilder implements ToXContent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a Geolocation for suggestions. See {@link GeoContextMapping}.
|
||||
* Setup a Geolocation for suggestions. See {@link GeolocationContextMapping}.
|
||||
* @param lat Latitude of the location
|
||||
* @param lon Longitude of the Location
|
||||
* @return this
|
||||
*/
|
||||
public T addGeoLocation(String name, double lat, double lon) {
|
||||
return addContextQuery(GeolocationContextMapping.query(name, lat, lon));
|
||||
public T addGeoLocation(String name, double lat, double lon, int ... precisions) {
|
||||
return addContextQuery(GeolocationContextMapping.query(name, lat, lon, precisions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a Geolocation for suggestions. See {@link GeoContextMapping}.
|
||||
* Setup a Geolocation for suggestions. See {@link GeolocationContextMapping}.
|
||||
* @param lat Latitude of the location
|
||||
* @param lon Longitude of the Location
|
||||
* @param precisions precisions as string var-args
|
||||
* @return this
|
||||
*/
|
||||
public T addGeoLocationWithPrecision(String name, double lat, double lon, String ... precisions) {
|
||||
return addContextQuery(GeolocationContextMapping.query(name, lat, lon, precisions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a Geolocation for suggestions. See {@link GeolocationContextMapping}.
|
||||
* @param geohash Geohash of the location
|
||||
* @return this
|
||||
*/
|
||||
@ -160,8 +171,8 @@ public class SuggestBuilder implements ToXContent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a Category for suggestions. See {@link CategoryMapping}.
|
||||
* @param category name of the category
|
||||
* Setup a Category for suggestions. See {@link CategoryContextMapping}.
|
||||
* @param categories name of the category
|
||||
* @return this
|
||||
*/
|
||||
public T addCategory(String name, CharSequence...categories) {
|
||||
@ -169,8 +180,8 @@ public class SuggestBuilder implements ToXContent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a Category for suggestions. See {@link CategoryMapping}.
|
||||
* @param category name of the category
|
||||
* Setup a Category for suggestions. See {@link CategoryContextMapping}.
|
||||
* @param categories name of the category
|
||||
* @return this
|
||||
*/
|
||||
public T addCategory(String name, Iterable<? extends CharSequence> categories) {
|
||||
@ -179,7 +190,7 @@ public class SuggestBuilder implements ToXContent {
|
||||
|
||||
/**
|
||||
* Setup a Context Field for suggestions. See {@link CategoryContextMapping}.
|
||||
* @param category name of the category
|
||||
* @param fieldvalues name of the category
|
||||
* @return this
|
||||
*/
|
||||
public T addContextField(String name, CharSequence...fieldvalues) {
|
||||
@ -188,7 +199,7 @@ public class SuggestBuilder implements ToXContent {
|
||||
|
||||
/**
|
||||
* Setup a Context Field for suggestions. See {@link CategoryContextMapping}.
|
||||
* @param category name of the category
|
||||
* @param fieldvalues name of the category
|
||||
* @return this
|
||||
*/
|
||||
public T addContextField(String name, Iterable<? extends CharSequence> fieldvalues) {
|
||||
@ -242,7 +253,7 @@ public class SuggestBuilder implements ToXContent {
|
||||
/**
|
||||
* Sets from what field to fetch the candidate suggestions from. This is an
|
||||
* required option and needs to be set via this setter or
|
||||
* {@link org.elasticsearch.search.suggest.SuggestBuilder.TermSuggestionBuilder#setField(String)}
|
||||
* {@link org.elasticsearch.search.suggest.term.TermSuggestionBuilder#field(String)}
|
||||
* method
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.elasticsearch.search.suggest.context;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.lucene.analysis.PrefixAnalyzer;
|
||||
@ -235,16 +236,18 @@ public class CategoryContextMapping extends ContextMapping {
|
||||
|
||||
@Override
|
||||
protected TokenStream wrapTokenStream(Document doc, TokenStream stream) {
|
||||
if(values != null) {
|
||||
if (values != null) {
|
||||
return new PrefixAnalyzer.PrefixTokenFilter(stream, ContextMapping.SEPARATOR, values);
|
||||
// if fieldname is default, BUT our default values are set, we take that one
|
||||
} else if ((doc.getFields(fieldname).length == 0 || fieldname.equals(DEFAULT_FIELDNAME)) && defaultValues.iterator().hasNext()) {
|
||||
return new PrefixAnalyzer.PrefixTokenFilter(stream, ContextMapping.SEPARATOR, defaultValues);
|
||||
} else {
|
||||
IndexableField[] fields = doc.getFields(fieldname);
|
||||
ArrayList<CharSequence> values = new ArrayList<>(fields.length);
|
||||
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
values.add(fields[i].stringValue());
|
||||
}
|
||||
|
||||
|
||||
return new PrefixAnalyzer.PrefixTokenFilter(stream, ContextMapping.SEPARATOR, values);
|
||||
}
|
||||
}
|
||||
@ -252,12 +255,11 @@ public class CategoryContextMapping extends ContextMapping {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("FieldConfig(" + fieldname + " = [");
|
||||
Iterator<? extends CharSequence> value = this.defaultValues.iterator();
|
||||
if (value.hasNext()) {
|
||||
sb.append(value.next());
|
||||
while (value.hasNext()) {
|
||||
sb.append(", ").append(value.next());
|
||||
}
|
||||
if (this.values != null && this.values.iterator().hasNext()) {
|
||||
sb.append("(").append(Joiner.on(", ").join(this.values.iterator())).append(")");
|
||||
}
|
||||
if (this.defaultValues != null && this.defaultValues.iterator().hasNext()) {
|
||||
sb.append(" default(").append(Joiner.on(", ").join(this.defaultValues.iterator())).append(")");
|
||||
}
|
||||
return sb.append("])").toString();
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
* length of the geohashes
|
||||
* @param neighbors
|
||||
* should neighbors be indexed
|
||||
* @param defaultLocation
|
||||
* @param defaultLocations
|
||||
* location to use, if it is not provided by the document
|
||||
*/
|
||||
protected GeolocationContextMapping(String name, int[] precision, boolean neighbors, Collection<String> defaultLocations, String fieldName) {
|
||||
@ -158,7 +158,16 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
builder.addDefaultLocation(location.toString());
|
||||
}
|
||||
} else if (def instanceof String) {
|
||||
builder.addDefaultLocation(def.toString());
|
||||
builder.addDefaultLocation(def.toString());
|
||||
} else if (def instanceof Map) {
|
||||
Map<String, Object> latlonMap = (Map<String, Object>) def;
|
||||
if (!latlonMap.containsKey("lat") || !(latlonMap.get("lat") instanceof Double)) {
|
||||
throw new ElasticsearchParseException("field [" + FIELD_MISSING + "] map must have field lat and a valid latitude");
|
||||
}
|
||||
if (!latlonMap.containsKey("lon") || !(latlonMap.get("lon") instanceof Double)) {
|
||||
throw new ElasticsearchParseException("field [" + FIELD_MISSING + "] map must have field lon and a valid longitude");
|
||||
}
|
||||
builder.addDefaultLocation(Double.valueOf(latlonMap.get("lat").toString()), Double.valueOf(latlonMap.get("lon").toString()));
|
||||
} else {
|
||||
throw new ElasticsearchParseException("field [" + FIELD_MISSING + "] must be of type string or list");
|
||||
}
|
||||
@ -264,8 +273,16 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
* longitude of the location
|
||||
* @return new geolocation query
|
||||
*/
|
||||
public static GeoQuery query(String name, double lat, double lon) {
|
||||
return query(name, GeoHashUtils.encode(lat, lon));
|
||||
public static GeoQuery query(String name, double lat, double lon, int ... precisions) {
|
||||
return query(name, GeoHashUtils.encode(lat, lon), precisions);
|
||||
}
|
||||
|
||||
public static GeoQuery query(String name, double lat, double lon, String ... precisions) {
|
||||
int precisionInts[] = new int[precisions.length];
|
||||
for (int i = 0 ; i < precisions.length; i++) {
|
||||
precisionInts[i] = GeoUtils.geoHashLevelsForPrecision(precisions[i]);
|
||||
}
|
||||
return query(name, GeoHashUtils.encode(lat, lon), precisionInts);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -275,8 +292,8 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
* geohash of the location
|
||||
* @return new geolocation query
|
||||
*/
|
||||
public static GeoQuery query(String name, String geohash) {
|
||||
return new GeoQuery(name, geohash);
|
||||
public static GeoQuery query(String name, String geohash, int ... precisions) {
|
||||
return new GeoQuery(name, geohash, precisions);
|
||||
}
|
||||
|
||||
private static final int parsePrecision(XContentParser parser) throws IOException, ElasticsearchParseException {
|
||||
@ -338,6 +355,7 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
}
|
||||
} else if (FIELD_VALUE.equals(fieldName)) {
|
||||
if(Double.isNaN(lon) && Double.isNaN(lat)) {
|
||||
parser.nextToken();
|
||||
point = GeoUtils.parseGeoPoint(parser);
|
||||
} else {
|
||||
throw new ElasticsearchParseException("only lat/lon or [" + FIELD_VALUE + "] is allowed");
|
||||
@ -450,7 +468,7 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
/**
|
||||
* Set the precision use o make suggestions
|
||||
*
|
||||
* @param precision
|
||||
* @param meters
|
||||
* precision as distance in meters
|
||||
* @return this
|
||||
*/
|
||||
@ -466,7 +484,7 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
/**
|
||||
* Set the precision use o make suggestions
|
||||
*
|
||||
* @param precision
|
||||
* @param level
|
||||
* maximum length of geohashes
|
||||
* @return this
|
||||
*/
|
||||
@ -504,7 +522,7 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
* Set a default location that should be used, if no location is
|
||||
* provided by the query
|
||||
*
|
||||
* @param geohash
|
||||
* @param geohashes
|
||||
* geohash of the default location
|
||||
* @return this
|
||||
*/
|
||||
@ -578,15 +596,28 @@ public class GeolocationContextMapping extends ContextMapping {
|
||||
if (locations == null || locations.size() == 0) {
|
||||
if(mapping.fieldName != null) {
|
||||
IndexableField[] fields = doc.getFields(mapping.fieldName);
|
||||
if(fields.length > 0) {
|
||||
if(fields.length == 0) {
|
||||
IndexableField[] lonFields = doc.getFields(mapping.fieldName + ".lon");
|
||||
IndexableField[] latFields = doc.getFields(mapping.fieldName + ".lat");
|
||||
if (lonFields.length > 0 && latFields.length > 0) {
|
||||
geohashes = new ArrayList<>(fields.length);
|
||||
GeoPoint spare = new GeoPoint();
|
||||
for (int i = 0 ; i < lonFields.length ; i++) {
|
||||
IndexableField lonField = lonFields[i];
|
||||
IndexableField latField = latFields[i];
|
||||
spare.reset(latField.numericValue().doubleValue(), lonField.numericValue().doubleValue());
|
||||
geohashes.add(spare.geohash());
|
||||
}
|
||||
} else {
|
||||
geohashes = mapping.defaultLocations;
|
||||
}
|
||||
} else {
|
||||
geohashes = new ArrayList<>(fields.length);
|
||||
GeoPoint spare = new GeoPoint();
|
||||
for (IndexableField field : fields) {
|
||||
spare.resetFromString(field.stringValue());
|
||||
geohashes.add(spare.geohash());
|
||||
}
|
||||
} else {
|
||||
geohashes = mapping.defaultLocations;
|
||||
}
|
||||
} else {
|
||||
geohashes = mapping.defaultLocations;
|
||||
|
@ -18,11 +18,14 @@
|
||||
*/
|
||||
package org.elasticsearch.search.suggest;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
|
||||
import org.elasticsearch.action.suggest.SuggestRequest;
|
||||
import org.elasticsearch.action.suggest.SuggestRequestBuilder;
|
||||
import org.elasticsearch.action.suggest.SuggestResponse;
|
||||
import org.elasticsearch.common.geo.GeoHashUtils;
|
||||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.search.suggest.Suggest.Suggestion;
|
||||
@ -35,14 +38,16 @@ import org.elasticsearch.search.suggest.context.ContextBuilder;
|
||||
import org.elasticsearch.search.suggest.context.ContextMapping;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.*;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchGeoAssertions.assertDistance;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
@ -96,7 +101,7 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
client().admin().indices().prepareRefresh(INDEX).get();
|
||||
|
||||
String suggestionName = RandomStrings.randomAsciiOfLength(new Random(), 10);
|
||||
String suggestionName = randomAsciiOfLength(10);
|
||||
CompletionSuggestionBuilder context = new CompletionSuggestionBuilder(suggestionName).field(FIELD).text("h").size(10)
|
||||
.addGeoLocation("st", 52.52, 13.4);
|
||||
|
||||
@ -106,7 +111,7 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
assertEquals(suggestResponse.getSuggest().size(), 1);
|
||||
assertEquals("Hotel Amsterdam in Berlin", suggestResponse.getSuggest().getSuggestion(suggestionName).iterator().next().getOptions().iterator().next().getText().string());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGeoField() throws Exception {
|
||||
|
||||
@ -158,7 +163,7 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
refresh();
|
||||
|
||||
String suggestionName = RandomStrings.randomAsciiOfLength(new Random(), 10);
|
||||
String suggestionName = randomAsciiOfLength(10);
|
||||
CompletionSuggestionBuilder context = new CompletionSuggestionBuilder(suggestionName).field(FIELD).text("h").size(10)
|
||||
.addGeoLocation("st", 52.52, 13.4);
|
||||
SuggestRequestBuilder suggestionRequest = client().prepareSuggest(INDEX).addSuggestion(context);
|
||||
@ -466,9 +471,225 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
assertFieldSuggestions(types[2], "w", "Whitemane, Kofi");
|
||||
}
|
||||
|
||||
public void assertGeoSuggestionsInRange(String location, String suggest, double precision) throws IOException {
|
||||
@Test // issue 5525, default location didnt work with lat/lon map, and did not set default location appropriately
|
||||
public void testGeoContextDefaultMapping() throws Exception {
|
||||
GeoPoint berlinAlexanderplatz = GeoHashUtils.decode("u33dc1");
|
||||
|
||||
String suggestionName = RandomStrings.randomAsciiOfLength(new Random(), 10);
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject()
|
||||
.startObject("poi").startObject("properties").startObject("suggest")
|
||||
.field("type", "completion")
|
||||
.startObject("context").startObject("location")
|
||||
.field("type", "geo")
|
||||
.startObject("default").field("lat", berlinAlexanderplatz.lat()).field("lon", berlinAlexanderplatz.lon()).endObject()
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().endObject()
|
||||
.endObject();
|
||||
|
||||
assertAcked(prepareCreate(INDEX).addMapping("poi", xContentBuilder));
|
||||
ensureYellow();
|
||||
|
||||
index(INDEX, "poi", "1", jsonBuilder().startObject().startObject("suggest").field("input", "Berlin Alexanderplatz").endObject().endObject());
|
||||
refresh();
|
||||
|
||||
CompletionSuggestionBuilder suggestionBuilder = new CompletionSuggestionBuilder("suggestion").field("suggest").text("b").size(10).addGeoLocation("location", berlinAlexanderplatz.lat(), berlinAlexanderplatz.lon());
|
||||
SuggestResponse suggestResponse = client().prepareSuggest(INDEX).addSuggestion(suggestionBuilder).get();
|
||||
assertSuggestion(suggestResponse.getSuggest(), 0, "suggestion", "Berlin Alexanderplatz");
|
||||
}
|
||||
|
||||
@Test // issue 5525, setting the path of a category context and then indexing a document without that field returned an error
|
||||
public void testThatMissingPrefixesForContextReturnException() throws Exception {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject()
|
||||
.startObject("service").startObject("properties").startObject("suggest")
|
||||
.field("type", "completion")
|
||||
.startObject("context").startObject("color")
|
||||
.field("type", "category")
|
||||
.field("path", "color")
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().endObject()
|
||||
.endObject();
|
||||
|
||||
assertAcked(prepareCreate(INDEX).addMapping("service", xContentBuilder));
|
||||
ensureYellow();
|
||||
|
||||
// now index a document with color field
|
||||
index(INDEX, "service", "1", jsonBuilder().startObject().field("color", "red").startObject("suggest").field("input", "backback").endObject().endObject());
|
||||
|
||||
// now index a document without a color field
|
||||
try {
|
||||
index(INDEX, "service", "2", jsonBuilder().startObject().startObject("suggest").field("input", "backback").endObject().endObject());
|
||||
fail("index operation was not supposed to be succesful");
|
||||
} catch (ElasticsearchIllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), containsString("one or more prefixes needed"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test // issue 5525, the geo point parser did not work when the lat/lon values were inside of a value object
|
||||
public void testThatLocationVenueCanBeParsedAsDocumented() throws Exception {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject()
|
||||
.startObject("poi").startObject("properties").startObject("suggest")
|
||||
.field("type", "completion")
|
||||
.startObject("context").startObject("location")
|
||||
.field("type", "geo")
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().endObject()
|
||||
.endObject();
|
||||
|
||||
assertAcked(prepareCreate(INDEX).addMapping("poi", xContentBuilder));
|
||||
ensureYellow();
|
||||
|
||||
SuggestRequest suggestRequest = new SuggestRequest(INDEX);
|
||||
XContentBuilder builder = jsonBuilder().startObject()
|
||||
.startObject("suggest")
|
||||
.field("text", "m")
|
||||
.startObject("completion")
|
||||
.field("field", "suggest")
|
||||
.startObject("context").startObject("location").startObject("value").field("lat", 0).field("lon", 0).endObject().field("precision", "1km").endObject().endObject()
|
||||
.endObject()
|
||||
.endObject()
|
||||
.endObject();
|
||||
suggestRequest.suggest(builder.bytes());
|
||||
|
||||
SuggestResponse suggestResponse = client().suggest(suggestRequest).get();
|
||||
assertNoFailures(suggestResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatCategoryDefaultWorks() throws Exception {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject()
|
||||
.startObject("item").startObject("properties").startObject("suggest")
|
||||
.field("type", "completion")
|
||||
.startObject("context").startObject("color")
|
||||
.field("type", "category").field("default", "red")
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().endObject()
|
||||
.endObject();
|
||||
|
||||
assertAcked(prepareCreate(INDEX).addMapping("item", xContentBuilder));
|
||||
ensureYellow();
|
||||
|
||||
index(INDEX, "item", "1", jsonBuilder().startObject().startObject("suggest").field("input", "Hoodie red").endObject().endObject());
|
||||
index(INDEX, "item", "2", jsonBuilder().startObject().startObject("suggest").field("input", "Hoodie blue").startObject("context").field("color", "blue").endObject().endObject().endObject());
|
||||
refresh();
|
||||
|
||||
CompletionSuggestionBuilder suggestionBuilder = new CompletionSuggestionBuilder("suggestion").field("suggest").text("h").size(10).addContextField("color", "red");
|
||||
SuggestResponse suggestResponse = client().prepareSuggest(INDEX).addSuggestion(suggestionBuilder).get();
|
||||
assertSuggestion(suggestResponse.getSuggest(), 0, "suggestion", "Hoodie red");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatDefaultCategoryAndPathWorks() throws Exception {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject()
|
||||
.startObject("item").startObject("properties").startObject("suggest")
|
||||
.field("type", "completion")
|
||||
.startObject("context").startObject("color")
|
||||
.field("type", "category")
|
||||
.field("default", "red")
|
||||
.field("path", "color")
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().endObject()
|
||||
.endObject();
|
||||
|
||||
assertAcked(prepareCreate(INDEX).addMapping("item", xContentBuilder));
|
||||
ensureYellow();
|
||||
|
||||
index(INDEX, "item", "1", jsonBuilder().startObject().startObject("suggest").field("input", "Hoodie red").endObject().endObject());
|
||||
index(INDEX, "item", "2", jsonBuilder().startObject().startObject("suggest").field("input", "Hoodie blue").endObject().field("color", "blue").endObject());
|
||||
refresh();
|
||||
|
||||
CompletionSuggestionBuilder suggestionBuilder = new CompletionSuggestionBuilder("suggestion").field("suggest").text("h").size(10).addContextField("color", "red");
|
||||
SuggestResponse suggestResponse = client().prepareSuggest(INDEX).addSuggestion(suggestionBuilder).get();
|
||||
assertSuggestion(suggestResponse.getSuggest(), 0, "suggestion", "Hoodie red");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatGeoPrecisionIsWorking() throws Exception {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject()
|
||||
.startObject("item").startObject("properties").startObject("suggest")
|
||||
.field("type", "completion")
|
||||
.startObject("context").startObject("location")
|
||||
.field("type", "geo")
|
||||
.field("precision", 4) // this means geo hashes with a length of four are used, like u345
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().endObject()
|
||||
.endObject();
|
||||
|
||||
assertAcked(prepareCreate(INDEX).addMapping("item", xContentBuilder));
|
||||
ensureYellow();
|
||||
|
||||
// lets create some locations by geohashes in different cells with the precision 4
|
||||
// this means, that poelchaustr is not a neighour to alexanderplatz, but they share the same prefix until the fourth char!
|
||||
GeoPoint alexanderplatz = GeoHashUtils.decode("u33dc1");
|
||||
GeoPoint poelchaustr = GeoHashUtils.decode("u33du5");
|
||||
GeoPoint dahlem = GeoHashUtils.decode("u336q"); // berlin dahlem, should be included with that precision
|
||||
GeoPoint middleOfNoWhere = GeoHashUtils.decode("u334"); // location for west from berlin, should not be included in any suggestions
|
||||
|
||||
index(INDEX, "item", "1", jsonBuilder().startObject().startObject("suggest").field("input", "Berlin Alexanderplatz").field("weight", 3).startObject("context").startObject("location").field("lat", alexanderplatz.lat()).field("lon", alexanderplatz.lon()).endObject().endObject().endObject().endObject());
|
||||
index(INDEX, "item", "2", jsonBuilder().startObject().startObject("suggest").field("input", "Berlin Poelchaustr.").field("weight", 2).startObject("context").startObject("location").field("lat", poelchaustr.lat()).field("lon", poelchaustr.lon()).endObject().endObject().endObject().endObject());
|
||||
index(INDEX, "item", "3", jsonBuilder().startObject().startObject("suggest").field("input", "Berlin Far Away").field("weight", 1).startObject("context").startObject("location").field("lat", middleOfNoWhere.lat()).field("lon", middleOfNoWhere.lon()).endObject().endObject().endObject().endObject());
|
||||
index(INDEX, "item", "4", jsonBuilder().startObject().startObject("suggest").field("input", "Berlin Dahlem").field("weight", 1).startObject("context").startObject("location").field("lat", dahlem.lat()).field("lon", dahlem.lon()).endObject().endObject().endObject().endObject());
|
||||
refresh();
|
||||
|
||||
CompletionSuggestionBuilder suggestionBuilder = new CompletionSuggestionBuilder("suggestion").field("suggest").text("b").size(10).addGeoLocation("location", alexanderplatz.lat(), alexanderplatz.lon());
|
||||
SuggestResponse suggestResponse = client().prepareSuggest(INDEX).addSuggestion(suggestionBuilder).get();
|
||||
assertSuggestion(suggestResponse.getSuggest(), 0, "suggestion", "Berlin Alexanderplatz", "Berlin Poelchaustr.", "Berlin Dahlem");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatNeighborsCanBeExcluded() throws Exception {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject()
|
||||
.startObject("item").startObject("properties").startObject("suggest")
|
||||
.field("type", "completion")
|
||||
.startObject("context").startObject("location")
|
||||
.field("type", "geo")
|
||||
.field("precision", 6)
|
||||
.field("neighbors", false)
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().endObject()
|
||||
.endObject();
|
||||
|
||||
assertAcked(prepareCreate(INDEX).addMapping("item", xContentBuilder));
|
||||
ensureYellow();
|
||||
|
||||
GeoPoint alexanderplatz = GeoHashUtils.decode("u33dc1");
|
||||
// does not look like it, but is a direct neighbor
|
||||
// this test would fail, if the precision was set 4, as then both cells would be the same, u33d
|
||||
GeoPoint cellNeighbourOfAlexanderplatz = GeoHashUtils.decode("u33dbc");
|
||||
|
||||
index(INDEX, "item", "1", jsonBuilder().startObject().startObject("suggest").field("input", "Berlin Alexanderplatz").field("weight", 3).startObject("context").startObject("location").field("lat", alexanderplatz.lat()).field("lon", alexanderplatz.lon()).endObject().endObject().endObject().endObject());
|
||||
index(INDEX, "item", "2", jsonBuilder().startObject().startObject("suggest").field("input", "Berlin Hackescher Markt").field("weight", 2).startObject("context").startObject("location").field("lat", cellNeighbourOfAlexanderplatz.lat()).field("lon", cellNeighbourOfAlexanderplatz.lon()).endObject().endObject().endObject().endObject());
|
||||
refresh();
|
||||
|
||||
CompletionSuggestionBuilder suggestionBuilder = new CompletionSuggestionBuilder("suggestion").field("suggest").text("b").size(10).addGeoLocation("location", alexanderplatz.lat(), alexanderplatz.lon());
|
||||
SuggestResponse suggestResponse = client().prepareSuggest(INDEX).addSuggestion(suggestionBuilder).get();
|
||||
assertSuggestion(suggestResponse.getSuggest(), 0, "suggestion", "Berlin Alexanderplatz");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatGeoPathCanBeSelected() throws Exception {
|
||||
XContentBuilder xContentBuilder = jsonBuilder().startObject()
|
||||
.startObject("item").startObject("properties").startObject("suggest")
|
||||
.field("type", "completion")
|
||||
.startObject("context").startObject("location")
|
||||
.field("type", "geo")
|
||||
.field("path", "loc")
|
||||
.endObject().endObject()
|
||||
.endObject().endObject().endObject()
|
||||
.endObject();
|
||||
|
||||
assertAcked(prepareCreate(INDEX).addMapping("item", xContentBuilder));
|
||||
ensureYellow();
|
||||
|
||||
GeoPoint alexanderplatz = GeoHashUtils.decode("u33dc1");
|
||||
index(INDEX, "item", "1", jsonBuilder().startObject().startObject("suggest").field("input", "Berlin Alexanderplatz").endObject().startObject("loc").field("lat", alexanderplatz.lat()).field("lon", alexanderplatz.lon()).endObject().endObject());
|
||||
refresh();
|
||||
|
||||
CompletionSuggestionBuilder suggestionBuilder = new CompletionSuggestionBuilder("suggestion").field("suggest").text("b").size(10).addGeoLocation("location", alexanderplatz.lat(), alexanderplatz.lon());
|
||||
SuggestResponse suggestResponse = client().prepareSuggest(INDEX).addSuggestion(suggestionBuilder).get();
|
||||
assertSuggestion(suggestResponse.getSuggest(), 0, "suggestion", "Berlin Alexanderplatz");
|
||||
}
|
||||
|
||||
public void assertGeoSuggestionsInRange(String location, String suggest, double precision) throws IOException {
|
||||
String suggestionName = randomAsciiOfLength(10);
|
||||
CompletionSuggestionBuilder context = new CompletionSuggestionBuilder(suggestionName).field(FIELD).text(suggest).size(10)
|
||||
.addGeoLocation("st", location);
|
||||
SuggestRequestBuilder suggestionRequest = client().prepareSuggest(INDEX).addSuggestion(context);
|
||||
@ -491,7 +712,7 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
}
|
||||
|
||||
public void assertPrefixSuggestions(long prefix, String suggest, String... hits) throws IOException {
|
||||
String suggestionName = RandomStrings.randomAsciiOfLength(new Random(), 10);
|
||||
String suggestionName = randomAsciiOfLength(10);
|
||||
CompletionSuggestionBuilder context = new CompletionSuggestionBuilder(suggestionName).field(FIELD).text(suggest)
|
||||
.size(hits.length + 1).addCategory("st", Long.toString(prefix));
|
||||
SuggestRequestBuilder suggestionRequest = client().prepareSuggest(INDEX).addSuggestion(context);
|
||||
@ -516,7 +737,7 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
}
|
||||
|
||||
public void assertContextWithFuzzySuggestions(String[] prefix1, String[] prefix2, String suggest, String... hits) throws IOException {
|
||||
String suggestionName = RandomStrings.randomAsciiOfLength(new Random(), 10);
|
||||
String suggestionName = randomAsciiOfLength(10);
|
||||
CompletionSuggestionFuzzyBuilder context = new CompletionSuggestionFuzzyBuilder(suggestionName).field(FIELD).text(suggest)
|
||||
.size(hits.length + 10).addContextField("st", prefix1).addContextField("nd", prefix2).setFuzziness(Fuzziness.TWO);
|
||||
SuggestRequestBuilder suggestionRequest = client().prepareSuggest(INDEX).addSuggestion(context);
|
||||
@ -544,7 +765,7 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
}
|
||||
|
||||
public void assertFieldSuggestions(String value, String suggest, String... hits) throws IOException {
|
||||
String suggestionName = RandomStrings.randomAsciiOfLength(new Random(), 10);
|
||||
String suggestionName = randomAsciiOfLength(10);
|
||||
CompletionSuggestionBuilder context = new CompletionSuggestionBuilder(suggestionName).field(FIELD).text(suggest).size(10)
|
||||
.addContextField("st", value);
|
||||
SuggestRequestBuilder suggestionRequest = client().prepareSuggest(INDEX).addSuggestion(context);
|
||||
@ -569,7 +790,7 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
}
|
||||
|
||||
public void assertDoubleFieldSuggestions(String field1, String field2, String suggest, String... hits) throws IOException {
|
||||
String suggestionName = RandomStrings.randomAsciiOfLength(new Random(), 10);
|
||||
String suggestionName = randomAsciiOfLength(10);
|
||||
CompletionSuggestionBuilder context = new CompletionSuggestionBuilder(suggestionName).field(FIELD).text(suggest).size(10)
|
||||
.addContextField("st", field1).addContextField("nd", field2);
|
||||
SuggestRequestBuilder suggestionRequest = client().prepareSuggest(INDEX).addSuggestion(context);
|
||||
@ -593,7 +814,7 @@ public class ContextSuggestSearchTests extends ElasticsearchIntegrationTest {
|
||||
}
|
||||
|
||||
public void assertMultiContextSuggestions(String value1, String value2, String suggest, String... hits) throws IOException {
|
||||
String suggestionName = RandomStrings.randomAsciiOfLength(new Random(), 10);
|
||||
String suggestionName = randomAsciiOfLength(10);
|
||||
CompletionSuggestionBuilder context = new CompletionSuggestionBuilder(suggestionName).field(FIELD).text(suggest).size(10)
|
||||
.addContextField("st", value1).addContextField("nd", value2);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user