Mapper plugin overwrites multifield mapping

If you define some specific mapping for your file content, such as the following:

```javascript
{
    "person": {
        "properties": {
            "file": {
                "type": "attachment",
                "path": "full",
                "fields": {
                    "file": {
                        "type": "multifield",
                        "fields": {
                            "file": { "type": "string" },
                            "suggest": { "type": "string" }
                        }
                    }
                }
            }
        }
    }
}
```

And then, if you ask back the mapping, you get:

```javascript
{
   "person":{
      "properties":{
         "file":{
            "type":"attachment",
            "path":"full",
            "fields":{
               "file":{
                  "type":"string"
               },
               "author":{
                  "type":"string"
               },
               "title":{
                  "type":"string"
               },
               "name":{
                  "type":"string"
               },
               "date":{
                  "type":"date",
                  "format":"dateOptionalTime"
               },
               "keywords":{
                  "type":"string"
               },
               "content_type":{
                  "type":"string"
               }
            }
         }
      }
   }
}
```

All your settings have been overwrited by the mapper plugin.

Closes #37.
This commit is contained in:
David Pilato 2013-08-19 11:01:02 +02:00
parent d2e2fb5cdf
commit d7a2e7e2ff
3 changed files with 186 additions and 38 deletions

View File

@ -27,6 +27,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.*; import org.elasticsearch.index.mapper.*;
import org.elasticsearch.index.mapper.core.DateFieldMapper; import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.index.mapper.core.StringFieldMapper; import org.elasticsearch.index.mapper.core.StringFieldMapper;
import org.elasticsearch.index.mapper.multifield.MultiFieldMapper;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
@ -69,19 +70,19 @@ public class AttachmentMapper implements Mapper {
private Integer defaultIndexedChars = null; private Integer defaultIndexedChars = null;
private StringFieldMapper.Builder contentBuilder; private Mapper.Builder contentBuilder;
private StringFieldMapper.Builder titleBuilder = stringField("title"); private Mapper.Builder titleBuilder = stringField("title");
private StringFieldMapper.Builder nameBuilder = stringField("name"); private Mapper.Builder nameBuilder = stringField("name");
private StringFieldMapper.Builder authorBuilder = stringField("author"); private Mapper.Builder authorBuilder = stringField("author");
private StringFieldMapper.Builder keywordsBuilder = stringField("keywords"); private Mapper.Builder keywordsBuilder = stringField("keywords");
private DateFieldMapper.Builder dateBuilder = dateField("date"); private Mapper.Builder dateBuilder = dateField("date");
private StringFieldMapper.Builder contentTypeBuilder = stringField("content_type"); private Mapper.Builder contentTypeBuilder = stringField("content_type");
public Builder(String name) { public Builder(String name) {
super(name); super(name);
@ -99,37 +100,37 @@ public class AttachmentMapper implements Mapper {
return this; return this;
} }
public Builder content(StringFieldMapper.Builder content) { public Builder content(Mapper.Builder content) {
this.contentBuilder = content; this.contentBuilder = content;
return this; return this;
} }
public Builder date(DateFieldMapper.Builder date) { public Builder date(Mapper.Builder date) {
this.dateBuilder = date; this.dateBuilder = date;
return this; return this;
} }
public Builder author(StringFieldMapper.Builder author) { public Builder author(Mapper.Builder author) {
this.authorBuilder = author; this.authorBuilder = author;
return this; return this;
} }
public Builder title(StringFieldMapper.Builder title) { public Builder title(Mapper.Builder title) {
this.titleBuilder = title; this.titleBuilder = title;
return this; return this;
} }
public Builder name(StringFieldMapper.Builder name) { public Builder name(Mapper.Builder name) {
this.nameBuilder = name; this.nameBuilder = name;
return this; return this;
} }
public Builder keywords(StringFieldMapper.Builder keywords) { public Builder keywords(Mapper.Builder keywords) {
this.keywordsBuilder = keywords; this.keywordsBuilder = keywords;
return this; return this;
} }
public Builder contentType(StringFieldMapper.Builder contentType) { public Builder contentType(Mapper.Builder contentType) {
this.contentTypeBuilder = contentType; this.contentTypeBuilder = contentType;
return this; return this;
} }
@ -140,16 +141,16 @@ public class AttachmentMapper implements Mapper {
context.path().pathType(pathType); context.path().pathType(pathType);
// create the content mapper under the actual name // create the content mapper under the actual name
StringFieldMapper contentMapper = contentBuilder.build(context); Mapper contentMapper = contentBuilder.build(context);
// create the DC one under the name // create the DC one under the name
context.path().add(name); context.path().add(name);
DateFieldMapper dateMapper = dateBuilder.build(context); Mapper dateMapper = dateBuilder.build(context);
StringFieldMapper authorMapper = authorBuilder.build(context); Mapper authorMapper = authorBuilder.build(context);
StringFieldMapper titleMapper = titleBuilder.build(context); Mapper titleMapper = titleBuilder.build(context);
StringFieldMapper nameMapper = nameBuilder.build(context); Mapper nameMapper = nameBuilder.build(context);
StringFieldMapper keywordsMapper = keywordsBuilder.build(context); Mapper keywordsMapper = keywordsBuilder.build(context);
StringFieldMapper contentTypeMapper = contentTypeBuilder.build(context); Mapper contentTypeMapper = contentTypeBuilder.build(context);
context.path().remove(); context.path().remove();
context.path().pathType(origPathType); context.path().pathType(origPathType);
@ -199,21 +200,30 @@ public class AttachmentMapper implements Mapper {
String propName = entry1.getKey(); String propName = entry1.getKey();
Object propNode = entry1.getValue(); Object propNode = entry1.getValue();
// Check if we have a multifield here
boolean isMultifield = false;
if (propNode != null && propNode instanceof Map) {
Object oType = ((Map<String, Object>) propNode).get("type");
if (oType != null && oType.equals(MultiFieldMapper.CONTENT_TYPE)) {
isMultifield = true;
}
}
if (name.equals(propName)) { if (name.equals(propName)) {
// that is the content // that is the content
builder.content((StringFieldMapper.Builder) parserContext.typeParser("string").parse(name, (Map<String, Object>) propNode, parserContext)); builder.content(parserContext.typeParser(isMultifield? MultiFieldMapper.CONTENT_TYPE:StringFieldMapper.CONTENT_TYPE).parse(name, (Map<String, Object>) propNode, parserContext));
} else if ("date".equals(propName)) { } else if ("date".equals(propName)) {
builder.date((DateFieldMapper.Builder) parserContext.typeParser("date").parse("date", (Map<String, Object>) propNode, parserContext)); builder.date(parserContext.typeParser(isMultifield? MultiFieldMapper.CONTENT_TYPE:DateFieldMapper.CONTENT_TYPE).parse("date", (Map<String, Object>) propNode, parserContext));
} else if ("title".equals(propName)) { } else if ("title".equals(propName)) {
builder.title((StringFieldMapper.Builder) parserContext.typeParser("string").parse("title", (Map<String, Object>) propNode, parserContext)); builder.title(parserContext.typeParser(isMultifield? MultiFieldMapper.CONTENT_TYPE:StringFieldMapper.CONTENT_TYPE).parse("title", (Map<String, Object>) propNode, parserContext));
} else if ("name".equals(propName)) { } else if ("name".equals(propName)) {
builder.name((StringFieldMapper.Builder) parserContext.typeParser("string").parse("name", (Map<String, Object>) propNode, parserContext)); builder.name(parserContext.typeParser(isMultifield? MultiFieldMapper.CONTENT_TYPE:StringFieldMapper.CONTENT_TYPE).parse("name", (Map<String, Object>) propNode, parserContext));
} else if ("author".equals(propName)) { } else if ("author".equals(propName)) {
builder.author((StringFieldMapper.Builder) parserContext.typeParser("string").parse("author", (Map<String, Object>) propNode, parserContext)); builder.author(parserContext.typeParser(isMultifield? MultiFieldMapper.CONTENT_TYPE:StringFieldMapper.CONTENT_TYPE).parse("author", (Map<String, Object>) propNode, parserContext));
} else if ("keywords".equals(propName)) { } else if ("keywords".equals(propName)) {
builder.keywords((StringFieldMapper.Builder) parserContext.typeParser("string").parse("keywords", (Map<String, Object>) propNode, parserContext)); builder.keywords(parserContext.typeParser(isMultifield? MultiFieldMapper.CONTENT_TYPE:StringFieldMapper.CONTENT_TYPE).parse("keywords", (Map<String, Object>) propNode, parserContext));
} else if ("content_type".equals(propName)) { } else if ("content_type".equals(propName)) {
builder.contentType((StringFieldMapper.Builder) parserContext.typeParser("string").parse("content_type", (Map<String, Object>) propNode, parserContext)); builder.contentType(parserContext.typeParser(isMultifield? MultiFieldMapper.CONTENT_TYPE:StringFieldMapper.CONTENT_TYPE).parse("content_type", (Map<String, Object>) propNode, parserContext));
} }
} }
} }
@ -229,23 +239,23 @@ public class AttachmentMapper implements Mapper {
private final int defaultIndexedChars; private final int defaultIndexedChars;
private final StringFieldMapper contentMapper; private final Mapper contentMapper;
private final DateFieldMapper dateMapper; private final Mapper dateMapper;
private final StringFieldMapper authorMapper; private final Mapper authorMapper;
private final StringFieldMapper titleMapper; private final Mapper titleMapper;
private final StringFieldMapper nameMapper; private final Mapper nameMapper;
private final StringFieldMapper keywordsMapper; private final Mapper keywordsMapper;
private final StringFieldMapper contentTypeMapper; private final Mapper contentTypeMapper;
public AttachmentMapper(String name, ContentPath.Type pathType, int defaultIndexedChars, StringFieldMapper contentMapper, public AttachmentMapper(String name, ContentPath.Type pathType, int defaultIndexedChars, Mapper contentMapper,
DateFieldMapper dateMapper, StringFieldMapper titleMapper, StringFieldMapper nameMapper, StringFieldMapper authorMapper, Mapper dateMapper, Mapper titleMapper, Mapper nameMapper, Mapper authorMapper,
StringFieldMapper keywordsMapper, StringFieldMapper contentTypeMapper) { Mapper keywordsMapper, Mapper contentTypeMapper) {
this.name = name; this.name = name;
this.pathType = pathType; this.pathType = pathType;
this.defaultIndexedChars = defaultIndexedChars; this.defaultIndexedChars = defaultIndexedChars;

View File

@ -0,0 +1,77 @@
/*
* Licensed to ElasticSearch and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. ElasticSearch licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.mapper.xcontent;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.DocumentMapperParser;
import org.elasticsearch.index.mapper.attachment.AttachmentMapper;
import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.index.mapper.core.StringFieldMapper;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.elasticsearch.common.io.Streams.copyToStringFromClasspath;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
/**
*
*/
@Test
public class MultifieldAttachmentMapperTests {
private DocumentMapperParser mapperParser;
@BeforeClass
public void setupMapperParser() {
mapperParser = new DocumentMapperParser(new Index("test"), new AnalysisService(new Index("test")), null, null);
mapperParser.putTypeParser(AttachmentMapper.CONTENT_TYPE, new AttachmentMapper.TypeParser());
}
@Test
public void testSimpleMappings() throws Exception {
String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/multifield-mapping.json");
DocumentMapper docMapper = mapperParser.parse(mapping);
assertThat(docMapper.mappers().fullName("file").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.suggest").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.date").mapper(), instanceOf(DateFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.date.string").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.title").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.title.suggest").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.name").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.name.suggest").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.author").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.author.suggest").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.keywords").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.keywords.suggest").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.content_type").mapper(), instanceOf(StringFieldMapper.class));
assertThat(docMapper.mappers().fullName("file.content_type.suggest").mapper(), instanceOf(StringFieldMapper.class));
}
}

View File

@ -0,0 +1,61 @@
{
"person": {
"properties": {
"file": {
"type": "attachment",
"path": "full",
"fields": {
"file": {
"type": "multi_field",
"fields": {
"file": { "type": "string" },
"suggest": { "type": "string" }
}
},
"date": {
"type": "multi_field",
"fields": {
"date": { "type": "date" },
"string": { "type": "string" }
}
},
"title": {
"type": "multi_field",
"fields": {
"title": { "type": "string" },
"suggest": { "type": "string" }
}
},
"name": {
"type": "multi_field",
"fields": {
"name": { "type": "string" },
"suggest": { "type": "string" }
}
},
"author": {
"type": "multi_field",
"fields": {
"author": { "type": "string" },
"suggest": { "type": "string" }
}
},
"keywords": {
"type": "multi_field",
"fields": {
"keywords": { "type": "string" },
"suggest": { "type": "string" }
}
},
"content_type": {
"type": "multi_field",
"fields": {
"content_type": { "type": "string" },
"suggest": { "type": "string" }
}
}
}
}
}
}
}