Fix attachment mapper to expose subfields.

The content mapper is now true subfield. There is limited backcompat
support for the previous behavior of indexing and querying as the main
field name. While indexes pre ES 2.0 can still be read, the content
must now be queried with `FIELDNAME.content`.
This commit is contained in:
Ryan Ernst 2015-05-11 23:18:17 -07:00
parent 1c030f6f75
commit 765afb655e
15 changed files with 102 additions and 105 deletions

View File

@ -25,6 +25,9 @@ import org.apache.lucene.util.Constants;
import org.apache.tika.Tika;
import org.apache.tika.language.LanguageIdentifier;
import org.apache.tika.metadata.Metadata;
import org.elasticsearch.Version;
import org.elasticsearch.common.collect.Iterators;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.io.stream.BytesStreamInput;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.ESLoggerFactory;
@ -76,6 +79,7 @@ public class AttachmentMapper extends AbstractFieldMapper<Object> {
}
public static class FieldNames {
public static final String CONTENT = "content";
public static final String TITLE = "title";
public static final String NAME = "name";
public static final String AUTHOR = "author";
@ -117,7 +121,7 @@ public class AttachmentMapper extends AbstractFieldMapper<Object> {
public Builder(String name) {
super(name, new FieldType(AbstractFieldMapper.Defaults.FIELD_TYPE));
this.builder = this;
this.contentBuilder = stringField(name);
this.contentBuilder = stringField(FieldNames.CONTENT);
}
public Builder pathType(ContentPath.Type pathType) {
@ -175,11 +179,21 @@ public class AttachmentMapper extends AbstractFieldMapper<Object> {
ContentPath.Type origPathType = context.path().pathType();
context.path().pathType(pathType);
// create the content mapper under the actual name
FieldMapper<?> contentMapper = (FieldMapper<?>) contentBuilder.build(context);
FieldMapper<?> contentMapper;
if (context.indexCreatedVersion().before(Version.V_2_0_0)) {
// old behavior, we need the content to be indexed under the attachment field name
if (contentBuilder instanceof AbstractFieldMapper.Builder == false) {
throw new IllegalStateException("content field for attachment must be a field mapper");
}
((AbstractFieldMapper.Builder)contentBuilder).indexName(name);
contentBuilder.name = name + "." + FieldNames.CONTENT;
contentMapper = (FieldMapper<?>) contentBuilder.build(context);
context.path().add(name);
} else {
context.path().add(name);
contentMapper = (FieldMapper<?>) contentBuilder.build(context);
}
// create the DC one under the name
context.path().add(name);
FieldMapper<?> dateMapper = (FieldMapper<?>) dateBuilder.build(context);
FieldMapper<?> authorMapper = (FieldMapper<?>) authorBuilder.build(context);
FieldMapper<?> titleMapper = (FieldMapper<?>) titleBuilder.build(context);
@ -228,7 +242,7 @@ public class AttachmentMapper extends AbstractFieldMapper<Object> {
* field1 : {
* type : "attachment",
* fields : {
* field1 : {type : "binary"},
* content : {type : "binary"},
* title : {store : "yes"},
* date : {store : "yes"},
* name : {store : "yes"},
@ -265,7 +279,7 @@ public class AttachmentMapper extends AbstractFieldMapper<Object> {
Map.Entry<String, Object> entry = iterator.next();
String fieldName = entry.getKey();
Object fieldNode = entry.getValue();
if (fieldName.equals("path")) {
if (fieldName.equals("path") && parserContext.indexVersionCreated().before(Version.V_2_0_0)) {
builder.pathType(parsePathType(name, fieldNode.toString()));
iterator.remove();
} else if (fieldName.equals("fields")) {
@ -278,11 +292,15 @@ public class AttachmentMapper extends AbstractFieldMapper<Object> {
Mapper.Builder<?, ?> mapperBuilder = findMapperBuilder(propNode, propName, parserContext);
if (parseMultiField((AbstractFieldMapper.Builder) mapperBuilder, fieldName, parserContext, propName, propNode)) {
fieldsIterator.remove();
} else if (propName.equals(name)) {
} else if (propName.equals(name) && parserContext.indexVersionCreated().before(Version.V_2_0_0)) {
builder.content(mapperBuilder);
fieldsIterator.remove();
} else {
switch (propName) {
case FieldNames.CONTENT:
builder.content(mapperBuilder);
fieldsIterator.remove();
break;
case FieldNames.DATE:
builder.date(mapperBuilder);
fieldsIterator.remove();
@ -592,20 +610,18 @@ public class AttachmentMapper extends AbstractFieldMapper<Object> {
}
@Override
public void traverse(FieldMapperListener fieldMapperListener) {
contentMapper.traverse(fieldMapperListener);
dateMapper.traverse(fieldMapperListener);
titleMapper.traverse(fieldMapperListener);
nameMapper.traverse(fieldMapperListener);
authorMapper.traverse(fieldMapperListener);
keywordsMapper.traverse(fieldMapperListener);
contentTypeMapper.traverse(fieldMapperListener);
contentLengthMapper.traverse(fieldMapperListener);
languageMapper.traverse(fieldMapperListener);
}
@Override
public void traverse(ObjectMapperListener objectMapperListener) {
public Iterator<Mapper> iterator() {
List<FieldMapper<?>> extras = Lists.newArrayList(
contentMapper,
dateMapper,
titleMapper,
nameMapper,
authorMapper,
keywordsMapper,
contentTypeMapper,
contentLengthMapper,
languageMapper);
return Iterators.concat(super.iterator(), extras.iterator());
}
@Override
@ -625,7 +641,9 @@ public class AttachmentMapper extends AbstractFieldMapper<Object> {
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(name());
builder.field("type", CONTENT_TYPE);
builder.field("path", pathType.name().toLowerCase());
if (indexCreatedBefore2x) {
builder.field("path", pathType.name().toLowerCase());
}
builder.startObject("fields");
contentMapper.toXContent(builder, params);

View File

@ -107,7 +107,8 @@ public class MapperTestUtils {
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
.put(settings)
.build();
return new DocumentMapperParser(new Index("test"), forcedSettings, MapperTestUtils.newAnalysisService(forcedSettings), null, null);
MapperService mapperService = new MapperService(new Index("test"), forcedSettings, newAnalysisService(forcedSettings), null, newSimilarityLookupService(forcedSettings), null);
return new DocumentMapperParser(new Index("test"), forcedSettings, mapperService, MapperTestUtils.newAnalysisService(forcedSettings), null, null);
}
/**

View File

@ -75,7 +75,7 @@ public class EncryptedAttachmentIntegrationTests extends AttachmentIntegrationTe
refresh();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("World").defaultField("file1")).execute().get();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("World").defaultField("file1.content")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
countResponse = client().prepareCount("test").setQuery(queryStringQuery("World").defaultField("hello")).execute().get();

View File

@ -73,7 +73,7 @@ public class SimpleAttachmentIntegrationTests extends AttachmentIntegrationTestC
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("test document").defaultField("file.title")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
countResponse = client().prepareCount("test").setQuery(queryStringQuery("tests the ability").defaultField("file")).execute().get();
countResponse = client().prepareCount("test").setQuery(queryStringQuery("tests the ability").defaultField("file.content")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
}
@ -88,10 +88,10 @@ public class SimpleAttachmentIntegrationTests extends AttachmentIntegrationTestC
index("test", "person", jsonBuilder().startObject().field("file").startObject().field("_content", txt).field("_indexed_chars", CONTENT_LENGTH_LIMIT).endObject());
refresh();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("BeforeLimit").defaultField("file")).execute().get();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("BeforeLimit").defaultField("file.content")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
countResponse = client().prepareCount("test").setQuery(queryStringQuery("AfterLimit").defaultField("file")).execute().get();
countResponse = client().prepareCount("test").setQuery(queryStringQuery("AfterLimit").defaultField("file.content")).execute().get();
assertThat(countResponse.getCount(), equalTo(0l));
}
@ -106,10 +106,10 @@ public class SimpleAttachmentIntegrationTests extends AttachmentIntegrationTestC
index("test", "person", jsonBuilder().startObject().field("file").startObject().field("_content", txt).field("_indexed_chars", CONTENT_LENGTH_LIMIT).endObject());
refresh();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("Begin").defaultField("file")).execute().get();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("Begin").defaultField("file.content")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
countResponse = client().prepareCount("test").setQuery(queryStringQuery("End").defaultField("file")).execute().get();
countResponse = client().prepareCount("test").setQuery(queryStringQuery("End").defaultField("file.content")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
}
@ -174,24 +174,7 @@ public class SimpleAttachmentIntegrationTests extends AttachmentIntegrationTestC
index("test", "person", jsonBuilder().startObject().field("file", txt).endObject());
refresh();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("Queen").defaultField("file")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
countResponse = client().prepareCount("test").setQuery(queryStringQuery("Queen").defaultField("copy")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
}
@Test @AwaitsFix(bugUrl = "rjernst please fix me")
public void testCopyToSubField() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/attachment/test/integration/simple/copy-to-subfield.json");
byte[] txt = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/attachment/test/sample-files/text-in-english.txt");
client().admin().indices().putMapping(putMappingRequest("test").type("person").source(mapping)).actionGet();
index("test", "person", jsonBuilder().startObject().field("file", txt).endObject());
refresh();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("Queen").defaultField("file")).execute().get();
CountResponse countResponse = client().prepareCount("test").setQuery(queryStringQuery("Queen").defaultField("file.content")).execute().get();
assertThatWithError(countResponse.getCount(), equalTo(1l));
countResponse = client().prepareCount("test").setQuery(queryStringQuery("Queen").defaultField("copy")).execute().get();
@ -209,14 +192,14 @@ public class SimpleAttachmentIntegrationTests extends AttachmentIntegrationTestC
refresh();
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(matchQuery("file", "apache tika"))
.addHighlightedField("file")
.setQuery(matchQuery("file.content", "apache tika"))
.addHighlightedField("file.content")
.setNoFields().get();
logger.info("{}", searchResponse);
if (assertThatWithError(searchResponse.getHits().getTotalHits(), equalTo(1l))) {
assertThat(searchResponse.getHits().getAt(0).getHighlightFields(), notNullValue());
assertThat(searchResponse.getHits().getAt(0).getHighlightFields().keySet(), contains("file"));
assertThat(searchResponse.getHits().getAt(0).getHighlightFields().keySet(), contains("file.content"));
searchResponse.getHits().getAt(0).getHighlightFields();
for (HighlightField highlightField : searchResponse.getHits().getAt(0).getHighlightFields().values()) {
for (Text fragment : highlightField.getFragments()) {

View File

@ -19,6 +19,8 @@
package org.elasticsearch.index.mapper.attachment.test.unit;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ElasticsearchTestCase;
@ -43,6 +45,7 @@ public class AttachmentUnitTestCase extends ElasticsearchTestCase {
public void createSettings() throws Exception {
testSettings = ImmutableSettings.builder()
.put("path.home", createTempDir())
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id)
.build();
}
}

View File

@ -61,7 +61,7 @@ public class EncryptedDocMapperTest extends AttachmentUnitTestCase {
.endObject().bytes();
ParseContext.Document doc = docMapper.parse(json).rootDoc();
assertThat(doc.get(docMapper.mappers().getMapper("file1").names().indexName()), containsString("World"));
assertThat(doc.get(docMapper.mappers().getMapper("file1.content").names().indexName()), containsString("World"));
assertThat(doc.get(docMapper.mappers().getMapper("file1.title").names().indexName()), equalTo("Hello"));
assertThat(doc.get(docMapper.mappers().getMapper("file1.author").names().indexName()), equalTo("kimchy"));
assertThat(doc.get(docMapper.mappers().getMapper("file1.keywords").names().indexName()), equalTo("elasticsearch,cool,bonsai"));
@ -101,7 +101,7 @@ public class EncryptedDocMapperTest extends AttachmentUnitTestCase {
assertThat(doc.get(docMapper.mappers().getMapper("file1.content_type").names().indexName()), nullValue());
assertThat(doc.getField(docMapper.mappers().getMapper("file1.content_length").names().indexName()), nullValue());
assertThat(doc.get(docMapper.mappers().getMapper("file2").names().indexName()), containsString("World"));
assertThat(doc.get(docMapper.mappers().getMapper("file2.content").names().indexName()), containsString("World"));
assertThat(doc.get(docMapper.mappers().getMapper("file2.title").names().indexName()), equalTo("Hello"));
assertThat(doc.get(docMapper.mappers().getMapper("file2.author").names().indexName()), equalTo("kimchy"));
assertThat(doc.get(docMapper.mappers().getMapper("file2.keywords").names().indexName()), equalTo("elasticsearch,cool,bonsai"));

View File

@ -19,6 +19,8 @@
package org.elasticsearch.index.mapper.attachment.test.unit;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
@ -64,7 +66,7 @@ public class MetadataMapperTest extends AttachmentUnitTestCase {
.endObject().bytes();
ParseContext.Document doc = docMapper.parse(json).rootDoc();
assertThat(doc.get(docMapper.mappers().getMapper("file").names().indexName()), containsString("World"));
assertThat(doc.get(docMapper.mappers().getMapper("file.content").names().indexName()), containsString("World"));
assertThat(doc.get(docMapper.mappers().getMapper("file.name").names().indexName()), equalTo(filename));
if (expectedDate == null) {
assertThat(doc.getField(docMapper.mappers().getMapper("file.date").names().indexName()), nullValue());

View File

@ -63,8 +63,8 @@ public class MultifieldAttachmentMapperTests extends AttachmentUnitTestCase {
DocumentMapper docMapper = mapperParser.parse(mapping);
assertThat(docMapper.mappers().getMapper("file"), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().getMapper("file.suggest"), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().getMapper("file.content"), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().getMapper("file.content.suggest"), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().getMapper("file.date"), instanceOf(DateFieldMapper.class));
assertThat(docMapper.mappers().getMapper("file.date.string"), instanceOf(StringFieldMapper.class));
@ -107,8 +107,8 @@ public class MultifieldAttachmentMapperTests extends AttachmentUnitTestCase {
.endObject()
.bytes());
assertThat(doc.rootDoc().getField("file"), notNullValue());
assertThat(doc.rootDoc().getField("file").stringValue(), is(originalText + "\n"));
assertThat(doc.rootDoc().getField("file.content"), notNullValue());
assertThat(doc.rootDoc().getField("file.content").stringValue(), is(originalText + "\n"));
assertThat(doc.rootDoc().getField("file.content_type"), notNullValue());
assertThat(doc.rootDoc().getField("file.content_type").stringValue(), is(contentType));
@ -117,8 +117,8 @@ public class MultifieldAttachmentMapperTests extends AttachmentUnitTestCase {
assertThat(doc.rootDoc().getField("file.content_length"), notNullValue());
assertThat(doc.rootDoc().getField("file.content_length").numericValue().intValue(), is(originalText.length()));
assertThat(doc.rootDoc().getField("file.suggest"), notNullValue());
assertThat(doc.rootDoc().getField("file.suggest").stringValue(), is(originalText + "\n"));
assertThat(doc.rootDoc().getField("file.content.suggest"), notNullValue());
assertThat(doc.rootDoc().getField("file.content.suggest").stringValue(), is(originalText + "\n"));
// Let's force some values
doc = documentMapper.parse("person", "1", XContentFactory.jsonBuilder()
@ -130,8 +130,8 @@ public class MultifieldAttachmentMapperTests extends AttachmentUnitTestCase {
.endObject()
.bytes());
assertThat(doc.rootDoc().getField("file"), notNullValue());
assertThat(doc.rootDoc().getField("file").stringValue(), is(originalText + "\n"));
assertThat(doc.rootDoc().getField("file.content"), notNullValue());
assertThat(doc.rootDoc().getField("file.content").stringValue(), is(originalText + "\n"));
assertThat(doc.rootDoc().getField("file.content_type"), notNullValue());
assertThat(doc.rootDoc().getField("file.content_type").stringValue(), is(contentType));
@ -140,8 +140,8 @@ public class MultifieldAttachmentMapperTests extends AttachmentUnitTestCase {
assertThat(doc.rootDoc().getField("file.content_length"), notNullValue());
assertThat(doc.rootDoc().getField("file.content_length").numericValue().intValue(), is(originalText.length()));
assertThat(doc.rootDoc().getField("file.suggest"), notNullValue());
assertThat(doc.rootDoc().getField("file.suggest").stringValue(), is(originalText + "\n"));
assertThat(doc.rootDoc().getField("file.content.suggest"), notNullValue());
assertThat(doc.rootDoc().getField("file.content.suggest").stringValue(), is(originalText + "\n"));
assertThat(doc.rootDoc().getField("file.name"), notNullValue());
assertThat(doc.rootDoc().getField("file.name").stringValue(), is(forcedName));

View File

@ -19,7 +19,10 @@
package org.elasticsearch.index.mapper.attachment.test.unit;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.DocumentMapperParser;
import org.elasticsearch.index.mapper.ParseContext;
@ -38,38 +41,48 @@ import static org.hamcrest.Matchers.*;
*/
public class SimpleAttachmentMapperTests extends AttachmentUnitTestCase {
private DocumentMapperParser mapperParser;
@Before
public void setupMapperParser() {
mapperParser = MapperTestUtils.newMapperParser(createTempDir());
mapperParser.putTypeParser(AttachmentMapper.CONTENT_TYPE, new AttachmentMapper.TypeParser());
}
@Test
public void testSimpleMappings() throws Exception {
DocumentMapperParser mapperParser = MapperTestUtils.newMapperParser(createTempDir());
mapperParser.putTypeParser(AttachmentMapper.CONTENT_TYPE, new AttachmentMapper.TypeParser());
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/attachment/test/unit/simple/test-mapping.json");
DocumentMapper docMapper = mapperParser.parse(mapping);
byte[] html = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/attachment/test/sample-files/testXHTML.html");
BytesReference json = jsonBuilder().startObject().field("_id", 1).field("file", html).endObject().bytes();
BytesReference json = jsonBuilder().startObject().field("file", html).endObject().bytes();
ParseContext.Document doc = docMapper.parse(json).rootDoc();
ParseContext.Document doc = docMapper.parse("person", "1", json).rootDoc();
assertThat(doc.get(docMapper.mappers().getMapper("file.content_type").names().indexName()), startsWith("application/xhtml+xml"));
assertThat(doc.get(docMapper.mappers().getMapper("file.title").names().indexName()), equalTo("XHTML test document"));
assertThat(doc.get(docMapper.mappers().getMapper("file").names().indexName()), containsString("This document tests the ability of Apache Tika to extract content"));
assertThat(doc.get(docMapper.mappers().getMapper("file.content").names().indexName()), containsString("This document tests the ability of Apache Tika to extract content"));
// re-parse it
String builtMapping = docMapper.mappingSource().string();
docMapper = mapperParser.parse(builtMapping);
json = jsonBuilder().startObject().field("_id", 1).field("file", html).endObject().bytes();
json = jsonBuilder().startObject().field("file", html).endObject().bytes();
doc = docMapper.parse(json).rootDoc();
doc = docMapper.parse("person", "1", json).rootDoc();
assertThat(doc.get(docMapper.mappers().getMapper("file.content_type").names().indexName()), startsWith("application/xhtml+xml"));
assertThat(doc.get(docMapper.mappers().getMapper("file.title").names().indexName()), equalTo("XHTML test document"));
assertThat(doc.get(docMapper.mappers().getMapper("file").names().indexName()), containsString("This document tests the ability of Apache Tika to extract content"));
assertThat(doc.get(docMapper.mappers().getMapper("file.content").names().indexName()), containsString("This document tests the ability of Apache Tika to extract content"));
}
public void testContentBackcompat() throws Exception {
DocumentMapperParser mapperParser = MapperTestUtils.newMapperParser(ImmutableSettings.builder()
.put("path.home", createTempDir())
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id)
.build());
mapperParser.putTypeParser(AttachmentMapper.CONTENT_TYPE, new AttachmentMapper.TypeParser());
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/attachment/test/unit/simple/test-mapping.json");
DocumentMapper docMapper = mapperParser.parse(mapping);
byte[] html = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/attachment/test/sample-files/testXHTML.html");
BytesReference json = jsonBuilder().startObject().field("file", html).endObject().bytes();
ParseContext.Document doc = docMapper.parse("person", "1", json).rootDoc();
assertThat(doc.get("file"), containsString("This document tests the ability of Apache Tika to extract content"));
}
}

View File

@ -133,16 +133,15 @@ public class VariousDocTest extends AttachmentUnitTestCase {
BytesReference json = jsonBuilder()
.startObject()
.field("_id", 1)
.startObject("file")
.field("_name", filename)
.field("_content", html)
.endObject()
.endObject().bytes();
ParseContext.Document doc = docMapper.parse(json).rootDoc();
ParseContext.Document doc = docMapper.parse("person", "1", json).rootDoc();
if (!errorExpected) {
assertThat(doc.get(docMapper.mappers().getMapper("file").names().indexName()), not(isEmptyOrNullString()));
assertThat(doc.get(docMapper.mappers().getMapper("file.content").names().indexName()), not(isEmptyOrNullString()));
logger.debug("-> extracted content: {}", doc.get(docMapper.mappers().getMapper("file").names().indexName()));
logger.debug("-> extracted metadata:");
printMetadataContent(doc, AUTHOR);

View File

@ -1,19 +0,0 @@
{
"person": {
"properties": {
"file": {
"type": "attachment",
"path": "full",
"fields": {
"file": {
"type": "string",
"copy_to": "copy"
}
}
},
"copy": {
"type": "string"
}
}
}
}

View File

@ -4,7 +4,7 @@
"file":{
"type":"attachment",
"fields": {
"file" : {
"content" : {
"type": "string",
"store" : "yes",
"term_vector": "with_positions_offsets"

View File

@ -3,7 +3,6 @@
"properties": {
"file": {
"type": "attachment",
"path": "full",
"fields": {
"date": { "type": "string" }
}

View File

@ -3,7 +3,6 @@
"properties": {
"file": {
"type": "attachment",
"path": "full",
"fields": {
"language": { "type": "string" }
}

View File

@ -3,9 +3,8 @@
"properties": {
"file": {
"type": "attachment",
"path": "full",
"fields": {
"file": {
"content": {
"type": "string",
"fields": {
"suggest": { "type": "string" }