Mappings: Remove support for new indexes using path setting in

object/nested fields or index_name in any field

Backcompat is still here for indexes created before 2.0.

closes #6677
This commit is contained in:
Ryan Ernst 2015-02-04 13:17:38 -08:00
parent 9362ba200d
commit c6968883a7
25 changed files with 80 additions and 162 deletions

View File

@ -159,7 +159,22 @@ def generate_index(client, version):
'index_analyzer': 'standard',
'search_analyzer': 'keyword',
'search_quote_analyzer': 'english',
}
}
mappings['index_name_and_path'] = {
'properties': {
'parent_multi_field': {
'type': 'string',
'path': 'just_name',
'fields': {
'raw': {'type': 'string', 'index': 'not_analyzed', 'index_name': 'raw_multi_field'}
}
},
'field_with_index_name': {
'type': 'string',
'index_name': 'custom_index_name_for_field'
}
}
}
client.indices.create(index='test', body={
'settings': {

View File

@ -60,8 +60,6 @@ You can also use wildcards. The field names can be any of the following:
[horizontal]
Full names:: the full path, including any parent object name the field is
part of (ex. `user.id`).
Index names:: the name of the lucene field (can be different than the
field name if the `index_name` option of the mapping is used).
Field names:: the name of the field without the path to it (ex. `id` for `{ "user" : { "id" : 1 } }`).
The above options are specified in the order the `field` parameter is resolved.
@ -76,12 +74,12 @@ For example, consider the following mapping:
"article": {
"properties": {
"id": { "type": "string" },
"title": { "type": "string", "index_name": "text" },
"abstract": { "type": "string", "index_name": "text" },
"title": { "type": "string"},
"abstract": { "type": "string"},
"author": {
"properties": {
"id": { "type": "string" },
"name": { "type": "string", "index_name": "author" }
"name": { "type": "string" }
}
}
}
@ -89,13 +87,12 @@ For example, consider the following mapping:
}
--------------------------------------------------
To select the `id` of the `author` field, you can use its full name `author.id`. Using `text` will return
the mapping of `abstract` as it is one of the fields which map to the Lucene field `text`. `name` will return
To select the `id` of the `author` field, you can use its full name `author.id`. `name` will return
the field `author.name`:
[source,js]
--------------------------------------------------
curl -XGET "http://localhost:9200/publications/_mapping/article/field/author.id,text,name"
curl -XGET "http://localhost:9200/publications/_mapping/article/field/author.id,abstract,name"
--------------------------------------------------
returns:
@ -105,10 +102,10 @@ returns:
{
"publications": {
"article": {
"text": {
"abstract": {
"full_name": "abstract",
"mapping": {
"abstract": { "type": "string", "index_name": "text" }
"abstract": { "type": "string" }
}
},
"author.id": {
@ -120,7 +117,7 @@ returns:
"name": {
"full_name": "author.name",
"mapping": {
"name": { "type": "string", "index_name": "author" }
"name": { "type": "string" }
}
}
}
@ -130,7 +127,7 @@ returns:
Note how the response always use the same fields specified in the request as keys.
The `full_name` in every entry contains the full name of the field whose mapping were returned.
This is useful when the request can refer to to multiple fields (like `text` above).
This is useful when the request can refer to to multiple fields.
[float]
=== Other options

View File

@ -43,7 +43,7 @@ Here is a sample mapping:
"properties" : {
"first" : {
"properties" : {
"location" : {"type" : "string", "store" : true, "index_name" : "firstLocation"}
"location" : {"type" : "string", "store" : true}
}
},
"last" : {

View File

@ -38,7 +38,7 @@ is a sample explicit mapping:
"tweet" : {
"properties" : {
"message" : {"type" : "string"},
"tags" : {"type" : "string", "index_name" : "tag"},
"tags" : {"type" : "string"},
"lists" : {
"properties" : {
"name" : {"type" : "string"},

View File

@ -12,16 +12,13 @@ setup:
t2:
type: string
obj:
path: just_name
properties:
t1:
type: string
i_t1:
type: string
index_name: t1
i_t3:
type: string
index_name: t3
- do:
indices.create:
@ -35,16 +32,13 @@ setup:
t2:
type: string
obj:
path: just_name
properties:
t1:
type: string
i_t1:
type: string
index_name: t1
i_t3:
type: string
index_name: t3
- do:
cluster.health:
@ -71,12 +65,9 @@ setup:
index: test_index
field: "t*"
# i_t1 matches the pattern using it's index name, but t1 already means a full name
# of a field and thus takes precedence.
- match: {test_index.mappings.test_type.t1.full_name: t1 }
- match: {test_index.mappings.test_type.t2.full_name: t2 }
- match: {test_index.mappings.test_type.t3.full_name: obj.i_t3 }
- length: {test_index.mappings.test_type: 3}
- length: {test_index.mappings.test_type: 2}
---
"Get field mapping with *t1 for fields":

View File

@ -35,6 +35,7 @@ import org.apache.lucene.queries.TermsFilter;
import org.apache.lucene.search.*;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.lucene.BytesRefs;
@ -259,16 +260,26 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
return builder;
}
public Names buildNames(BuilderContext context) {
return new Names(name, buildIndexName(context), indexName == null ? name : indexName, buildFullName(context), context.path().sourcePath());
protected Names buildNames(BuilderContext context) {
return new Names(name, buildIndexName(context), buildIndexNameClean(context), buildFullName(context), context.path().sourcePath());
}
public String buildIndexName(BuilderContext context) {
protected String buildIndexName(BuilderContext context) {
if (context.indexCreatedVersion().onOrAfter(Version.V_2_0_0)) {
return buildFullName(context);
}
String actualIndexName = indexName == null ? name : indexName;
return context.path().pathAsText(actualIndexName);
}
protected String buildIndexNameClean(BuilderContext context) {
if (context.indexCreatedVersion().onOrAfter(Version.V_2_0_0)) {
return buildFullName(context);
}
return indexName == null ? name : indexName;
}
public String buildFullName(BuilderContext context) {
protected String buildFullName(BuilderContext context) {
return context.path().fullPathAsText(name);
}
}
@ -287,6 +298,7 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
protected FieldDataType fieldDataType;
protected final MultiFields multiFields;
protected CopyTo copyTo;
protected final boolean writePre20Metadata;
protected AbstractFieldMapper(Names names, float boost, FieldType fieldType, Boolean docValues, NamedAnalyzer indexAnalyzer,
NamedAnalyzer searchAnalyzer, PostingsFormatProvider postingsFormat,
@ -340,6 +352,9 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
}
this.multiFields = multiFields;
this.copyTo = copyTo;
// the short circuit check to EMPTY here is necessary because some built in fields pass EMPTY for simplified ctors
this.writePre20Metadata = indexSettings != null && indexSettings.equals(ImmutableSettings.EMPTY) == false &&
Version.indexCreated(indexSettings).before(Version.V_2_0_0);
}
@Nullable
@ -690,7 +705,7 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
builder.field("type", contentType());
if (includeDefaults || !names.name().equals(names.indexNameClean())) {
if (writePre20Metadata && (includeDefaults || !names.name().equals(names.indexNameClean()))) {
builder.field("index_name", names.indexNameClean());
}

View File

@ -188,10 +188,8 @@ public class CompletionFieldMapper extends AbstractFieldMapper<String> {
} else if (Fields.MAX_INPUT_LENGTH.match(fieldName)) {
builder.maxInputLength(Integer.parseInt(fieldNode.toString()));
iterator.remove();
} else if ("fields".equals(fieldName) || "path".equals(fieldName)) {
if (parseMultiField(builder, name, parserContext, fieldName, fieldNode)) {
iterator.remove();
}
} else if (parseMultiField(builder, name, parserContext, fieldName, fieldNode)) {
iterator.remove();
} else if (fieldName.equals(Fields.CONTEXT)) {
builder.contextMapping(ContextBuilder.loadMappings(fieldNode, parserContext.indexVersionCreated()));
iterator.remove();

View File

@ -69,7 +69,7 @@ public class TypeParsers {
Map.Entry<String, Object> entry = iterator.next();
String fieldName = Strings.toUnderscoreCase(entry.getKey());
Object fieldNode = entry.getValue();
if (fieldName.equals("path")) {
if (fieldName.equals("path") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) {
pathType = parsePathType(name, fieldNode.toString());
iterator.remove();
} else if (fieldName.equals("fields")) {
@ -188,7 +188,7 @@ public class TypeParsers {
Map.Entry<String, Object> entry = iterator.next();
final String propName = Strings.toUnderscoreCase(entry.getKey());
final Object propNode = entry.getValue();
if (propName.equals("index_name")) {
if (propName.equals("index_name") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) {
builder.indexName(propNode.toString());
iterator.remove();
} else if (propName.equals("store")) {
@ -303,7 +303,7 @@ public class TypeParsers {
}
public static boolean parseMultiField(AbstractFieldMapper.Builder builder, String name, Mapper.TypeParser.ParserContext parserContext, String propName, Object propNode) {
if (propName.equals("path")) {
if (propName.equals("path") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) {
builder.multiFieldPathType(parsePathType(name, propNode.toString()));
return true;
} else if (propName.equals("fields")) {

View File

@ -29,6 +29,7 @@ import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.geo.GeoDistance;
@ -211,7 +212,7 @@ public class GeoPointFieldMapper extends AbstractFieldMapper<GeoPoint> implement
Map.Entry<String, Object> entry = iterator.next();
String fieldName = Strings.toUnderscoreCase(entry.getKey());
Object fieldNode = entry.getValue();
if (fieldName.equals("path")) {
if (fieldName.equals("path") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) {
builder.multiFieldPathType(parsePathType(name, fieldNode.toString()));
iterator.remove();
} else if (fieldName.equals("lat_lon")) {

View File

@ -28,6 +28,7 @@ import org.apache.lucene.search.Filter;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.CopyOnWriteHashMap;
@ -217,7 +218,7 @@ public class ObjectMapper implements Mapper, AllFieldMapper.IncludeInAll {
Map.Entry<String, Object> entry = iterator.next();
String fieldName = Strings.toUnderscoreCase(entry.getKey());
Object fieldNode = entry.getValue();
if (parseObjectOrDocumentTypeProperties(fieldName, fieldNode, parserContext, builder) || parseObjectProperties(name, fieldName, fieldNode, builder)) {
if (parseObjectOrDocumentTypeProperties(fieldName, fieldNode, parserContext, builder) || parseObjectProperties(name, fieldName, fieldNode, parserContext, builder)) {
iterator.remove();
}
}
@ -252,8 +253,8 @@ public class ObjectMapper implements Mapper, AllFieldMapper.IncludeInAll {
return false;
}
protected static boolean parseObjectProperties(String name, String fieldName, Object fieldNode, ObjectMapper.Builder builder) {
if (fieldName.equals("path")) {
protected static boolean parseObjectProperties(String name, String fieldName, Object fieldNode, ParserContext parserContext, ObjectMapper.Builder builder) {
if (fieldName.equals("path") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) {
builder.pathType(parsePathType(name, fieldNode.toString()));
return true;
}

View File

@ -32,6 +32,7 @@ import org.apache.lucene.search.join.BitDocIdSetFilter;
import org.apache.lucene.search.similarities.Similarity;
import org.apache.lucene.util.Bits;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.lucene.HashedBytesRef;
@ -40,6 +41,7 @@ import org.elasticsearch.common.lucene.search.NoCacheQuery;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.lucene.search.ResolvableFilter;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.analysis.AnalysisService;
@ -413,7 +415,9 @@ public class QueryParseContext {
return fieldMapping;
} else if (mapUnmappedFieldAsString){
StringFieldMapper.Builder builder = MapperBuilders.stringField(name);
StringFieldMapper stringFieldMapper = builder.build(new Mapper.BuilderContext(ImmutableSettings.EMPTY, new ContentPath(1)));
// it would be better to pass the real index settings, but they are not easily accessible from here...
Settings settings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, indexQueryParser.getIndexCreatedVersion()).build();
StringFieldMapper stringFieldMapper = builder.build(new Mapper.BuilderContext(settings, new ContentPath(1)));
return new MapperService.SmartNameFieldMappers(mapperService(), new FieldMappers(stringFieldMapper), null, false);
} else {
Version indexCreatedVersion = indexQueryParser.getIndexCreatedVersion();

View File

@ -29,8 +29,7 @@
"properties":{
"location":{
"type":"string",
"store":"yes",
"index_name":"firstLocation"
"store":"yes"
}
}
},

View File

@ -29,8 +29,7 @@
"properties":{
"location":{
"type":"string",
"store":"yes",
"index_name":"firstLocation"
"store":"yes"
}
}
},

View File

@ -29,8 +29,7 @@
"properties":{
"location":{
"type":"string",
"store":"yes",
"index_name":"firstLocation"
"store":"yes"
}
}
},

View File

@ -28,8 +28,7 @@
"properties":{
"location":{
"type":"string",
"store":"yes",
"index_name":"firstLocation"
"store":"yes"
}
}
},

View File

@ -27,8 +27,7 @@
"properties":{
"location":{
"type":"string",
"store":"yes",
"index_name":"firstLocation"
"store":"yes"
}
}
},

View File

@ -29,8 +29,7 @@
"properties":{
"location":{
"type":"string",
"store":"yes",
"index_name":"firstLocation"
"store":"yes"
}
}
},

View File

@ -39,20 +39,6 @@ public class PathMapperTests extends ElasticsearchSingleNodeTest {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/path/test-mapping.json");
DocumentMapper docMapper = createIndex("test").mapperService().documentMapperParser().parse(mapping);
assertThat(docMapper.mappers().indexName("first1"), notNullValue());
assertThat(docMapper.mappers().indexName("name1.first1"), nullValue());
assertThat(docMapper.mappers().indexName("last1"), nullValue());
assertThat(docMapper.mappers().indexName("i_last_1"), notNullValue());
assertThat(docMapper.mappers().indexName("name1.last1"), nullValue());
assertThat(docMapper.mappers().indexName("name1.i_last_1"), nullValue());
assertThat(docMapper.mappers().indexName("first2"), nullValue());
assertThat(docMapper.mappers().indexName("name2.first2"), notNullValue());
assertThat(docMapper.mappers().indexName("last2"), nullValue());
assertThat(docMapper.mappers().indexName("i_last_2"), nullValue());
assertThat(docMapper.mappers().indexName("name2.i_last_2"), notNullValue());
assertThat(docMapper.mappers().indexName("name2.last2"), nullValue());
// test full name
assertThat(docMapper.mappers().fullName("first1"), nullValue());
assertThat(docMapper.mappers().fullName("name1.first1"), notNullValue());

View File

@ -3,27 +3,23 @@
"properties":{
"name1":{
"type":"object",
"path":"just_name",
"properties":{
"first1":{
"type":"string"
},
"last1":{
"type":"string",
"index_name":"i_last_1"
"type":"string"
}
}
},
"name2":{
"type":"object",
"path":"full",
"properties":{
"first2":{
"type":"string"
},
"last2":{
"type":"string",
"index_name":"i_last_2"
"type":"string"
}
}
}

View File

@ -7,7 +7,6 @@
dynamic:false,
enabled:true,
_id:{
index_name:"_id"
},
_source:{
},
@ -38,8 +37,7 @@
properties:{
location:{
type:"string",
store:"yes",
index_name:"firstLocation"
store:"yes"
}
}
},
@ -64,8 +62,7 @@
type:"boolean"
},
dogs:{
type:"string",
index_name:"dog"
type:"string"
},
complex:{
type:"object",

View File

@ -2500,75 +2500,6 @@ public class HighlighterSearchTests extends ElasticsearchIntegrationTest {
}
}
@Test //https://github.com/elasticsearch/elasticsearch/issues/4116
public void testPostingsHighlighterCustomIndexName() {
assertAcked(prepareCreate("test")
.addMapping("type1", "field1", "type=string,index_options=offsets,index_name=my_field"));
ensureGreen();
client().prepareIndex("test", "type1", "1").setSource("field1", "First sentence. Second sentence.").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(matchQuery("field1", "first")).addHighlightedField("field1").get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first")).addHighlightedField("field1").get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first")).addHighlightedField("my_field").get();
assertHighlight(searchResponse, 0, "my_field", 0, 1, equalTo("<em>First</em> sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first"))
.addHighlightedField("field1").setHighlighterRequireFieldMatch(true).get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence."));
}
@Test
public void testFastVectorHighlighterCustomIndexName() {
assertAcked(prepareCreate("test")
.addMapping("type1", "field1", "type=string,term_vector=with_positions_offsets,index_name=my_field"));
ensureGreen();
client().prepareIndex("test", "type1", "1").setSource("field1", "First sentence. Second sentence.").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(matchQuery("field1", "first")).addHighlightedField("field1").get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence. Second sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first")).addHighlightedField("field1").get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence. Second sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first")).addHighlightedField("my_field").get();
assertHighlight(searchResponse, 0, "my_field", 0, 1, equalTo("<em>First</em> sentence. Second sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first"))
.addHighlightedField("field1").setHighlighterRequireFieldMatch(true).get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence. Second sentence."));
}
@Test
public void testPlainHighlighterCustomIndexName() {
assertAcked(prepareCreate("test")
.addMapping("type1", "field1", "type=string,index_name=my_field"));
ensureGreen();
client().prepareIndex("test", "type1", "1").setSource("field1", "First sentence. Second sentence.").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test").setQuery(matchQuery("field1", "first")).addHighlightedField("field1").get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence. Second sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first")).addHighlightedField("field1").get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence. Second sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first")).addHighlightedField("my_field").get();
assertHighlight(searchResponse, 0, "my_field", 0, 1, equalTo("<em>First</em> sentence. Second sentence."));
searchResponse = client().prepareSearch("test").setQuery(matchQuery("my_field", "first"))
.addHighlightedField("field1").setHighlighterRequireFieldMatch(true).get();
assertHighlight(searchResponse, 0, "field1", 0, 1, equalTo("<em>First</em> sentence. Second sentence."));
}
@Test
public void testFastVectorHighlighterPhraseBoost() throws Exception {
assertAcked(prepareCreate("test").addMapping("type1", type1TermVectorMapping()));

View File

@ -487,7 +487,6 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
.startObject("properties")
.startObject(FIELD)
.field("type", "string")
.field("path", "just_name") // The path can't be changed / upgraded
.endObject()
.endObject()
.endObject()
@ -500,7 +499,6 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
.startObject(TYPE).startObject("properties")
.startObject(FIELD)
.field("type", "multi_field")
.field("path", "just_name")
.startObject("fields")
.startObject(FIELD).field("type", "string").endObject()
.startObject("suggest").field("type", "completion").field("analyzer", "simple").endObject()
@ -520,7 +518,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
ensureGreen(INDEX);
SuggestResponse afterReindexingResponse = client().prepareSuggest(INDEX).addSuggestion(
SuggestBuilders.completionSuggestion("suggs").field("suggest").text("f").size(10)
SuggestBuilders.completionSuggestion("suggs").field(FIELD + ".suggest").text("f").size(10)
).execute().actionGet();
assertSuggestions(afterReindexingResponse, "suggs", "Foo Fighters");
}
@ -533,7 +531,6 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
.startObject("properties")
.startObject(FIELD)
.field("type", "string")
.field("path", "just_name") // The path can't be changed / upgraded
.endObject()
.endObject()
.endObject()
@ -546,7 +543,6 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
.startObject(TYPE).startObject("properties")
.startObject(FIELD)
.field("type", "string")
.field("path", "just_name") // Need to specify path again, to make sure that the `path` is known when this mapping is parsed and turned into DocumentMapper that we merge with.
.startObject("fields")
.startObject("suggest").field("type", "completion").field("analyzer", "simple").endObject()
.endObject()
@ -565,7 +561,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest {
ensureGreen(INDEX);
SuggestResponse afterReindexingResponse = client().prepareSuggest(INDEX).addSuggestion(
SuggestBuilders.completionSuggestion("suggs").field("suggest").text("f").size(10)
SuggestBuilders.completionSuggestion("suggs").field(FIELD + ".suggest").text("f").size(10)
).execute().actionGet();
assertSuggestions(afterReindexingResponse, "suggs", "Foo Fighters");
}

View File

@ -168,12 +168,11 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
.startObject("properties")
.startObject("name")
.field("type", "multi_field")
.field("path", "just_name")
.startObject("fields")
.startObject("name")
.field("type", "string")
.endObject()
.startObject("name_shingled")
.startObject("shingled")
.field("type", "string")
.field("analyzer", "biword")
.field("search_analyzer", "standard")
@ -192,7 +191,7 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
refresh();
DirectCandidateGenerator generator = candidateGenerator("name").prefixLength(0).minWordLength(0).suggestMode("always").maxEdits(2);
PhraseSuggestionBuilder phraseSuggestion = phraseSuggestion("did_you_mean").field("name_shingled")
PhraseSuggestionBuilder phraseSuggestion = phraseSuggestion("did_you_mean").field("name.shingled")
.addCandidateGenerator(generator)
.gramSize(3);
Suggest searchSuggest = searchSuggest( "ice tea", phraseSuggestion);
@ -244,12 +243,11 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
.startObject("properties")
.startObject("name")
.field("type", "multi_field")
.field("path", "just_name")
.startObject("fields")
.startObject("name")
.field("type", "string")
.endObject()
.startObject("name_shingled")
.startObject("shingled")
.field("type", "string")
.field("analyzer", "biword")
.field("search_analyzer", "standard")
@ -266,7 +264,7 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
client().prepareIndex("test", "type1").setSource("name", "I like ice cream."));
refresh();
PhraseSuggestionBuilder phraseSuggestion = phraseSuggestion("did_you_mean").field("name_shingled")
PhraseSuggestionBuilder phraseSuggestion = phraseSuggestion("did_you_mean").field("name.shingled")
.addCandidateGenerator(PhraseSuggestionBuilder.candidateGenerator("name").prefixLength(0).minWordLength(0).suggestMode("always").maxEdits(2))
.gramSize(3);
Suggest searchSuggest = searchSuggest( "ice tea", phraseSuggestion);
@ -794,7 +792,6 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
.startObject("properties")
.startObject("name")
.field("type", "multi_field")
.field("path", "just_name")
.startObject("fields")
.startObject("name")
.field("type", "string")
@ -840,7 +837,6 @@ public class SuggestSearchTests extends ElasticsearchIntegrationTest {
startObject("properties").
startObject("name").
field("type", "multi_field").
field("path", "just_name").
startObject("fields").
startObject("name").
field("type", "string").