more work on simplifying mapper parsing code
This commit is contained in:
parent
8d2123a452
commit
5fa072263d
|
@ -35,7 +35,6 @@ import org.elasticsearch.common.compress.lzf.LZF;
|
||||||
import org.elasticsearch.common.io.stream.BytesStreamInput;
|
import org.elasticsearch.common.io.stream.BytesStreamInput;
|
||||||
import org.elasticsearch.common.io.stream.CachedStreamInput;
|
import org.elasticsearch.common.io.stream.CachedStreamInput;
|
||||||
import org.elasticsearch.common.io.stream.LZFStreamInput;
|
import org.elasticsearch.common.io.stream.LZFStreamInput;
|
||||||
import org.elasticsearch.common.lucene.uid.UidField;
|
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.xcontent.ToXContent;
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
@ -133,10 +132,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
|
|
||||||
private UidFieldMapper uidFieldMapper = new UidFieldMapper();
|
|
||||||
|
|
||||||
private IdFieldMapper idFieldMapper = new IdFieldMapper();
|
|
||||||
|
|
||||||
private Map<Class<? extends RootMapper>, RootMapper> rootMappers = Maps.newHashMap();
|
private Map<Class<? extends RootMapper>, RootMapper> rootMappers = Maps.newHashMap();
|
||||||
|
|
||||||
private NamedAnalyzer indexAnalyzer;
|
private NamedAnalyzer indexAnalyzer;
|
||||||
|
@ -154,12 +149,14 @@ public class DocumentMapper implements ToXContent {
|
||||||
public Builder(String index, @Nullable Settings indexSettings, RootObjectMapper.Builder builder) {
|
public Builder(String index, @Nullable Settings indexSettings, RootObjectMapper.Builder builder) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.rootObjectMapper = builder.build(builderContext);
|
this.rootObjectMapper = builder.build(builderContext);
|
||||||
|
IdFieldMapper idFieldMapper = new IdFieldMapper();
|
||||||
if (indexSettings != null) {
|
if (indexSettings != null) {
|
||||||
String idIndexed = indexSettings.get("index.mapping._id.indexed");
|
String idIndexed = indexSettings.get("index.mapping._id.indexed");
|
||||||
if (idIndexed != null && Booleans.parseBoolean(idIndexed, false)) {
|
if (idIndexed != null && Booleans.parseBoolean(idIndexed, false)) {
|
||||||
idFieldMapper = new IdFieldMapper(Field.Index.NOT_ANALYZED);
|
idFieldMapper = new IdFieldMapper(Field.Index.NOT_ANALYZED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.rootMappers.put(IdFieldMapper.class, idFieldMapper);
|
||||||
// add default mappers
|
// add default mappers
|
||||||
this.rootMappers.put(SizeFieldMapper.class, new SizeFieldMapper());
|
this.rootMappers.put(SizeFieldMapper.class, new SizeFieldMapper());
|
||||||
this.rootMappers.put(IndexFieldMapper.class, new IndexFieldMapper());
|
this.rootMappers.put(IndexFieldMapper.class, new IndexFieldMapper());
|
||||||
|
@ -169,6 +166,7 @@ public class DocumentMapper implements ToXContent {
|
||||||
this.rootMappers.put(AnalyzerMapper.class, new AnalyzerMapper());
|
this.rootMappers.put(AnalyzerMapper.class, new AnalyzerMapper());
|
||||||
this.rootMappers.put(BoostFieldMapper.class, new BoostFieldMapper());
|
this.rootMappers.put(BoostFieldMapper.class, new BoostFieldMapper());
|
||||||
this.rootMappers.put(RoutingFieldMapper.class, new RoutingFieldMapper());
|
this.rootMappers.put(RoutingFieldMapper.class, new RoutingFieldMapper());
|
||||||
|
this.rootMappers.put(UidFieldMapper.class, new UidFieldMapper());
|
||||||
// don't add parent field, by default its "null"
|
// don't add parent field, by default its "null"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,16 +181,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder idField(IdFieldMapper.Builder builder) {
|
|
||||||
this.idFieldMapper = builder.build(builderContext);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder uidField(UidFieldMapper.Builder builder) {
|
|
||||||
this.uidFieldMapper = builder.build(builderContext);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder indexAnalyzer(NamedAnalyzer indexAnalyzer) {
|
public Builder indexAnalyzer(NamedAnalyzer indexAnalyzer) {
|
||||||
this.indexAnalyzer = indexAnalyzer;
|
this.indexAnalyzer = indexAnalyzer;
|
||||||
return this;
|
return this;
|
||||||
|
@ -213,7 +201,7 @@ public class DocumentMapper implements ToXContent {
|
||||||
|
|
||||||
public DocumentMapper build(DocumentMapperParser docMapperParser) {
|
public DocumentMapper build(DocumentMapperParser docMapperParser) {
|
||||||
Preconditions.checkNotNull(rootObjectMapper, "Mapper builder must have the root object mapper set");
|
Preconditions.checkNotNull(rootObjectMapper, "Mapper builder must have the root object mapper set");
|
||||||
return new DocumentMapper(index, docMapperParser, rootObjectMapper, meta, uidFieldMapper, idFieldMapper,
|
return new DocumentMapper(index, docMapperParser, rootObjectMapper, meta,
|
||||||
indexAnalyzer, searchAnalyzer,
|
indexAnalyzer, searchAnalyzer,
|
||||||
rootMappers);
|
rootMappers);
|
||||||
}
|
}
|
||||||
|
@ -236,10 +224,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
|
|
||||||
private volatile CompressedString mappingSource;
|
private volatile CompressedString mappingSource;
|
||||||
|
|
||||||
private final UidFieldMapper uidFieldMapper;
|
|
||||||
|
|
||||||
private final IdFieldMapper idFieldMapper;
|
|
||||||
|
|
||||||
private final RootObjectMapper rootObjectMapper;
|
private final RootObjectMapper rootObjectMapper;
|
||||||
|
|
||||||
private final ImmutableMap<Class<? extends RootMapper>, RootMapper> rootMappers;
|
private final ImmutableMap<Class<? extends RootMapper>, RootMapper> rootMappers;
|
||||||
|
@ -267,8 +251,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
public DocumentMapper(String index, DocumentMapperParser docMapperParser,
|
public DocumentMapper(String index, DocumentMapperParser docMapperParser,
|
||||||
RootObjectMapper rootObjectMapper,
|
RootObjectMapper rootObjectMapper,
|
||||||
ImmutableMap<String, Object> meta,
|
ImmutableMap<String, Object> meta,
|
||||||
UidFieldMapper uidFieldMapper,
|
|
||||||
IdFieldMapper idFieldMapper,
|
|
||||||
NamedAnalyzer indexAnalyzer, NamedAnalyzer searchAnalyzer,
|
NamedAnalyzer indexAnalyzer, NamedAnalyzer searchAnalyzer,
|
||||||
Map<Class<? extends RootMapper>, RootMapper> rootMappers) {
|
Map<Class<? extends RootMapper>, RootMapper> rootMappers) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
@ -276,8 +258,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
this.docMapperParser = docMapperParser;
|
this.docMapperParser = docMapperParser;
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
this.rootObjectMapper = rootObjectMapper;
|
this.rootObjectMapper = rootObjectMapper;
|
||||||
this.uidFieldMapper = uidFieldMapper;
|
|
||||||
this.idFieldMapper = idFieldMapper;
|
|
||||||
|
|
||||||
this.rootMappers = ImmutableMap.copyOf(rootMappers);
|
this.rootMappers = ImmutableMap.copyOf(rootMappers);
|
||||||
this.rootMappersOrdered = rootMappers.values().toArray(new RootMapper[rootMappers.values().size()]);
|
this.rootMappersOrdered = rootMappers.values().toArray(new RootMapper[rootMappers.values().size()]);
|
||||||
|
@ -294,7 +274,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
|
|
||||||
this.typeFilter = typeMapper().fieldFilter(type);
|
this.typeFilter = typeMapper().fieldFilter(type);
|
||||||
|
|
||||||
rootObjectMapper.putMapper(idFieldMapper);
|
|
||||||
if (rootMapper(ParentFieldMapper.class) != null) {
|
if (rootMapper(ParentFieldMapper.class) != null) {
|
||||||
// mark the routing field mapper as required
|
// mark the routing field mapper as required
|
||||||
rootMapper(RoutingFieldMapper.class).markAsRequired();
|
rootMapper(RoutingFieldMapper.class).markAsRequired();
|
||||||
|
@ -311,8 +290,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the basic ones
|
|
||||||
tempFieldMappers.add(uidFieldMapper);
|
|
||||||
// now traverse and get all the statically defined ones
|
// now traverse and get all the statically defined ones
|
||||||
rootObjectMapper.traverse(new FieldMapperListener() {
|
rootObjectMapper.traverse(new FieldMapperListener() {
|
||||||
@Override public void fieldMapper(FieldMapper fieldMapper) {
|
@Override public void fieldMapper(FieldMapper fieldMapper) {
|
||||||
|
@ -355,7 +332,7 @@ public class DocumentMapper implements ToXContent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public UidFieldMapper uidMapper() {
|
public UidFieldMapper uidMapper() {
|
||||||
return this.uidFieldMapper;
|
return rootMapper(UidFieldMapper.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked"}) public <T extends RootMapper> T rootMapper(Class<T> type) {
|
@SuppressWarnings({"unchecked"}) public <T extends RootMapper> T rootMapper(Class<T> type) {
|
||||||
|
@ -473,12 +450,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
rootMapper.preParse(context);
|
rootMapper.preParse(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the id if we have it so we can validate it later on, also, add the uid if we can
|
|
||||||
if (source.id() != null) {
|
|
||||||
context.id(source.id());
|
|
||||||
uidFieldMapper.parse(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!emptyDoc) {
|
if (!emptyDoc) {
|
||||||
rootObjectMapper.parse(context);
|
rootObjectMapper.parse(context);
|
||||||
}
|
}
|
||||||
|
@ -487,37 +458,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
parser.nextToken();
|
parser.nextToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we did not get the id, we need to parse the uid into the document now, after it was added
|
|
||||||
if (source.id() == null) {
|
|
||||||
if (context.id() == null) {
|
|
||||||
if (!source.flyweight()) {
|
|
||||||
throw new MapperParsingException("No id found while parsing the content source");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
uidFieldMapper.parse(context);
|
|
||||||
if (context.docs().size() > 1) {
|
|
||||||
UidField uidField = (UidField) context.doc().getFieldable(UidFieldMapper.NAME);
|
|
||||||
assert uidField != null;
|
|
||||||
// we need to go over the docs and add it...
|
|
||||||
for (int i = 1; i < context.docs().size(); i++) {
|
|
||||||
// we don't need to add it as a full uid field in nested docs, since we don't need versioning
|
|
||||||
context.docs().get(i).add(new Field(UidFieldMapper.NAME, uidField.uid(), Field.Store.NO, Field.Index.NOT_ANALYZED));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (context.parsedIdState() != ParseContext.ParsedIdState.PARSED) {
|
|
||||||
if (context.id() == null) {
|
|
||||||
if (!source.flyweight()) {
|
|
||||||
throw new MapperParsingException("No id mapping with [_id] found in the content, and not explicitly set");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// mark it as external, so we can parse it
|
|
||||||
context.parsedId(ParseContext.ParsedIdState.EXTERNAL);
|
|
||||||
idFieldMapper.parse(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (RootMapper rootMapper : rootMappersOrdered) {
|
for (RootMapper rootMapper : rootMappersOrdered) {
|
||||||
rootMapper.postParse(context);
|
rootMapper.postParse(context);
|
||||||
}
|
}
|
||||||
|
@ -556,7 +496,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
public void addFieldMapperListener(FieldMapperListener fieldMapperListener, boolean includeExisting) {
|
public void addFieldMapperListener(FieldMapperListener fieldMapperListener, boolean includeExisting) {
|
||||||
fieldMapperListeners.add(fieldMapperListener);
|
fieldMapperListeners.add(fieldMapperListener);
|
||||||
if (includeExisting) {
|
if (includeExisting) {
|
||||||
fieldMapperListener.fieldMapper(uidFieldMapper);
|
|
||||||
for (RootMapper rootMapper : rootMappersOrdered) {
|
for (RootMapper rootMapper : rootMappersOrdered) {
|
||||||
if (!rootMapper.includeInObject() && rootMapper instanceof FieldMapper) {
|
if (!rootMapper.includeInObject() && rootMapper instanceof FieldMapper) {
|
||||||
fieldMapperListener.fieldMapper((FieldMapper) rootMapper);
|
fieldMapperListener.fieldMapper((FieldMapper) rootMapper);
|
||||||
|
@ -624,7 +563,6 @@ public class DocumentMapper implements ToXContent {
|
||||||
public void close() {
|
public void close() {
|
||||||
cache.remove();
|
cache.remove();
|
||||||
rootObjectMapper.close();
|
rootObjectMapper.close();
|
||||||
idFieldMapper.close();
|
|
||||||
for (RootMapper rootMapper : rootMappersOrdered) {
|
for (RootMapper rootMapper : rootMappersOrdered) {
|
||||||
rootMapper.close();
|
rootMapper.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@ import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.elasticsearch.index.mapper.MapperBuilders.*;
|
import static org.elasticsearch.index.mapper.MapperBuilders.*;
|
||||||
import static org.elasticsearch.index.mapper.core.TypeParsers.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kimchy (shay.banon)
|
* @author kimchy (shay.banon)
|
||||||
|
@ -97,6 +96,8 @@ public class DocumentMapperParser extends AbstractIndexComponent {
|
||||||
.put(BoostFieldMapper.NAME, new BoostFieldMapper.TypeParser())
|
.put(BoostFieldMapper.NAME, new BoostFieldMapper.TypeParser())
|
||||||
.put(ParentFieldMapper.NAME, new ParentFieldMapper.TypeParser())
|
.put(ParentFieldMapper.NAME, new ParentFieldMapper.TypeParser())
|
||||||
.put(RoutingFieldMapper.NAME, new RoutingFieldMapper.TypeParser())
|
.put(RoutingFieldMapper.NAME, new RoutingFieldMapper.TypeParser())
|
||||||
|
.put(UidFieldMapper.NAME, new UidFieldMapper.TypeParser())
|
||||||
|
.put(IdFieldMapper.NAME, new IdFieldMapper.TypeParser())
|
||||||
.immutableMap();
|
.immutableMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,11 +162,7 @@ public class DocumentMapperParser extends AbstractIndexComponent {
|
||||||
String fieldName = Strings.toUnderscoreCase(entry.getKey());
|
String fieldName = Strings.toUnderscoreCase(entry.getKey());
|
||||||
Object fieldNode = entry.getValue();
|
Object fieldNode = entry.getValue();
|
||||||
|
|
||||||
if (IdFieldMapper.CONTENT_TYPE.equals(fieldName) || "idField".equals(fieldName)) {
|
if ("index_analyzer".equals(fieldName)) {
|
||||||
docBuilder.idField(parseIdField((Map<String, Object>) fieldNode, parserContext));
|
|
||||||
} else if (UidFieldMapper.CONTENT_TYPE.equals(fieldName) || "uidField".equals(fieldName)) {
|
|
||||||
docBuilder.uidField(parseUidField((Map<String, Object>) fieldNode, parserContext));
|
|
||||||
} else if ("index_analyzer".equals(fieldName)) {
|
|
||||||
docBuilder.indexAnalyzer(analysisService.analyzer(fieldNode.toString()));
|
docBuilder.indexAnalyzer(analysisService.analyzer(fieldNode.toString()));
|
||||||
} else if ("search_analyzer".equals(fieldName)) {
|
} else if ("search_analyzer".equals(fieldName)) {
|
||||||
docBuilder.searchAnalyzer(analysisService.analyzer(fieldNode.toString()));
|
docBuilder.searchAnalyzer(analysisService.analyzer(fieldNode.toString()));
|
||||||
|
@ -199,17 +196,6 @@ public class DocumentMapperParser extends AbstractIndexComponent {
|
||||||
return documentMapper;
|
return documentMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
private UidFieldMapper.Builder parseUidField(Map<String, Object> uidNode, Mapper.TypeParser.ParserContext parserContext) {
|
|
||||||
UidFieldMapper.Builder builder = uid();
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IdFieldMapper.Builder parseIdField(Map<String, Object> idNode, Mapper.TypeParser.ParserContext parserContext) {
|
|
||||||
IdFieldMapper.Builder builder = id();
|
|
||||||
parseField(builder, builder.name, idNode, parserContext);
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
private Tuple<String, Map<String, Object>> extractMapping(String type, String source) throws MapperParsingException {
|
private Tuple<String, Map<String, Object>> extractMapping(String type, String source) throws MapperParsingException {
|
||||||
Map<String, Object> root;
|
Map<String, Object> root;
|
||||||
|
|
|
@ -67,8 +67,6 @@ public class ParseContext {
|
||||||
|
|
||||||
private Map<String, String> ignoredValues = new HashMap<String, String>();
|
private Map<String, String> ignoredValues = new HashMap<String, String>();
|
||||||
|
|
||||||
private ParsedIdState parsedIdState;
|
|
||||||
|
|
||||||
private boolean mappersAdded = false;
|
private boolean mappersAdded = false;
|
||||||
|
|
||||||
private boolean externalValueSet;
|
private boolean externalValueSet;
|
||||||
|
@ -99,7 +97,6 @@ public class ParseContext {
|
||||||
this.sourceToParse = source;
|
this.sourceToParse = source;
|
||||||
this.source = source == null ? null : sourceToParse.source();
|
this.source = source == null ? null : sourceToParse.source();
|
||||||
this.path.reset();
|
this.path.reset();
|
||||||
this.parsedIdState = ParsedIdState.NO;
|
|
||||||
this.mappersAdded = false;
|
this.mappersAdded = false;
|
||||||
this.listener = listener == null ? DocumentMapper.ParseListener.EMPTY : listener;
|
this.listener = listener == null ? DocumentMapper.ParseListener.EMPTY : listener;
|
||||||
this.allEntries = new AllEntries();
|
this.allEntries = new AllEntries();
|
||||||
|
@ -193,14 +190,6 @@ public class ParseContext {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parsedId(ParsedIdState parsedIdState) {
|
|
||||||
this.parsedIdState = parsedIdState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParsedIdState parsedIdState() {
|
|
||||||
return this.parsedIdState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ignoredValue(String indexName, String value) {
|
public void ignoredValue(String indexName, String value) {
|
||||||
ignoredValues.put(indexName, value);
|
ignoredValues.put(indexName, value);
|
||||||
}
|
}
|
||||||
|
@ -273,10 +262,4 @@ public class ParseContext {
|
||||||
stringBuilder.setLength(0);
|
stringBuilder.setLength(0);
|
||||||
return this.stringBuilder;
|
return this.stringBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum ParsedIdState {
|
|
||||||
NO,
|
|
||||||
PARSED,
|
|
||||||
EXTERNAL
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,20 +24,26 @@ import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.Fieldable;
|
import org.apache.lucene.document.Fieldable;
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.index.mapper.InternalMapper;
|
import org.elasticsearch.index.mapper.InternalMapper;
|
||||||
import org.elasticsearch.index.mapper.Mapper;
|
import org.elasticsearch.index.mapper.Mapper;
|
||||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||||
import org.elasticsearch.index.mapper.MergeContext;
|
import org.elasticsearch.index.mapper.MergeContext;
|
||||||
import org.elasticsearch.index.mapper.MergeMappingException;
|
import org.elasticsearch.index.mapper.MergeMappingException;
|
||||||
import org.elasticsearch.index.mapper.ParseContext;
|
import org.elasticsearch.index.mapper.ParseContext;
|
||||||
|
import org.elasticsearch.index.mapper.RootMapper;
|
||||||
import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
|
import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.elasticsearch.index.mapper.MapperBuilders.*;
|
||||||
|
import static org.elasticsearch.index.mapper.core.TypeParsers.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kimchy (shay.banon)
|
* @author kimchy (shay.banon)
|
||||||
*/
|
*/
|
||||||
public class IdFieldMapper extends AbstractFieldMapper<String> implements InternalMapper {
|
public class IdFieldMapper extends AbstractFieldMapper<String> implements InternalMapper, RootMapper {
|
||||||
|
|
||||||
public static final String NAME = "_id";
|
public static final String NAME = "_id";
|
||||||
|
|
||||||
|
@ -68,6 +74,14 @@ public class IdFieldMapper extends AbstractFieldMapper<String> implements Intern
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class TypeParser implements Mapper.TypeParser {
|
||||||
|
@Override public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
|
||||||
|
IdFieldMapper.Builder builder = id();
|
||||||
|
parseField(builder, builder.name, node, parserContext);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IdFieldMapper() {
|
public IdFieldMapper() {
|
||||||
this(Defaults.NAME, Defaults.INDEX_NAME, Defaults.INDEX);
|
this(Defaults.NAME, Defaults.INDEX_NAME, Defaults.INDEX);
|
||||||
}
|
}
|
||||||
|
@ -108,28 +122,50 @@ public class IdFieldMapper extends AbstractFieldMapper<String> implements Intern
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void preParse(ParseContext context) throws IOException {
|
||||||
|
if (context.sourceToParse().id() != null) {
|
||||||
|
context.id(context.sourceToParse().id());
|
||||||
|
super.parse(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void postParse(ParseContext context) throws IOException {
|
||||||
|
if (context.id() == null && !context.sourceToParse().flyweight()) {
|
||||||
|
throw new MapperParsingException("No id found while parsing the content source");
|
||||||
|
}
|
||||||
|
// it either get built in the preParse phase, or get parsed...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void parse(ParseContext context) throws IOException {
|
||||||
|
super.parse(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void validate(ParseContext context) throws MapperParsingException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean includeInObject() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override protected Field parseCreateField(ParseContext context) throws IOException {
|
@Override protected Field parseCreateField(ParseContext context) throws IOException {
|
||||||
if (context.parsedIdState() == ParseContext.ParsedIdState.NO) {
|
XContentParser parser = context.parser();
|
||||||
String id = context.parser().text();
|
if (parser.currentName() != null && parser.currentName().equals(Defaults.NAME) && parser.currentToken().isValue()) {
|
||||||
|
// we are in the parse Phase
|
||||||
|
String id = parser.text();
|
||||||
if (context.id() != null && !context.id().equals(id)) {
|
if (context.id() != null && !context.id().equals(id)) {
|
||||||
throw new MapperParsingException("Provided id [" + context.id() + "] does not match the content one [" + id + "]");
|
throw new MapperParsingException("Provided id [" + context.id() + "] does not match the content one [" + id + "]");
|
||||||
}
|
}
|
||||||
context.id(id);
|
context.id(id);
|
||||||
context.parsedId(ParseContext.ParsedIdState.PARSED);
|
|
||||||
if (index == Field.Index.NO && store == Field.Store.NO) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new Field(names.indexName(), false, context.id(), store, index, termVector);
|
|
||||||
} else if (context.parsedIdState() == ParseContext.ParsedIdState.EXTERNAL) {
|
|
||||||
if (context.id() == null) {
|
|
||||||
throw new MapperParsingException("No id mapping with [" + names.name() + "] found in the content, and not explicitly set");
|
|
||||||
}
|
|
||||||
if (index == Field.Index.NO && store == Field.Store.NO) {
|
if (index == Field.Index.NO && store == Field.Store.NO) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new Field(names.indexName(), false, context.id(), store, index, termVector);
|
return new Field(names.indexName(), false, context.id(), store, index, termVector);
|
||||||
} else {
|
} else {
|
||||||
throw new MapperParsingException("Illegal parsed id state");
|
// we are in the pre/post parse phase
|
||||||
|
if (index == Field.Index.NO && store == Field.Store.NO) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Field(names.indexName(), false, context.id(), store, index, termVector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,15 +31,19 @@ import org.elasticsearch.index.mapper.MapperParsingException;
|
||||||
import org.elasticsearch.index.mapper.MergeContext;
|
import org.elasticsearch.index.mapper.MergeContext;
|
||||||
import org.elasticsearch.index.mapper.MergeMappingException;
|
import org.elasticsearch.index.mapper.MergeMappingException;
|
||||||
import org.elasticsearch.index.mapper.ParseContext;
|
import org.elasticsearch.index.mapper.ParseContext;
|
||||||
|
import org.elasticsearch.index.mapper.RootMapper;
|
||||||
import org.elasticsearch.index.mapper.Uid;
|
import org.elasticsearch.index.mapper.Uid;
|
||||||
import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
|
import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.elasticsearch.index.mapper.MapperBuilders.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kimchy (shay.banon)
|
* @author kimchy (shay.banon)
|
||||||
*/
|
*/
|
||||||
public class UidFieldMapper extends AbstractFieldMapper<Uid> implements InternalMapper {
|
public class UidFieldMapper extends AbstractFieldMapper<Uid> implements InternalMapper, RootMapper {
|
||||||
|
|
||||||
public static final String NAME = "_uid";
|
public static final String NAME = "_uid";
|
||||||
|
|
||||||
|
@ -68,6 +72,12 @@ public class UidFieldMapper extends AbstractFieldMapper<Uid> implements Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class TypeParser implements Mapper.TypeParser {
|
||||||
|
@Override public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
|
||||||
|
return uid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ThreadLocal<UidField> fieldCache = new ThreadLocal<UidField>() {
|
private ThreadLocal<UidField> fieldCache = new ThreadLocal<UidField>() {
|
||||||
@Override protected UidField initialValue() {
|
@Override protected UidField initialValue() {
|
||||||
return new UidField(names().indexName(), "", 0);
|
return new UidField(names().indexName(), "", 0);
|
||||||
|
@ -87,10 +97,48 @@ public class UidFieldMapper extends AbstractFieldMapper<Uid> implements Internal
|
||||||
Defaults.OMIT_NORMS, Defaults.OMIT_TERM_FREQ_AND_POSITIONS, Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER);
|
Defaults.OMIT_NORMS, Defaults.OMIT_TERM_FREQ_AND_POSITIONS, Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
|
@Override public void preParse(ParseContext context) throws IOException {
|
||||||
if (context.id() == null) {
|
// if we have the id provided, fill it, and parse now
|
||||||
|
if (context.sourceToParse().id() != null) {
|
||||||
|
context.id(context.sourceToParse().id());
|
||||||
|
super.parse(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void postParse(ParseContext context) throws IOException {
|
||||||
|
if (context.id() == null && !context.sourceToParse().flyweight()) {
|
||||||
throw new MapperParsingException("No id found while parsing the content source");
|
throw new MapperParsingException("No id found while parsing the content source");
|
||||||
}
|
}
|
||||||
|
// if we did not have the id as part of the sourceToParse, then we need to parse it here
|
||||||
|
// it would have been filled in the _id parse phase
|
||||||
|
if (context.sourceToParse().id() == null) {
|
||||||
|
super.parse(context);
|
||||||
|
// since we did not have the uid in the pre phase, we did not add it automatically to the nested docs
|
||||||
|
// as they were created we need to make sure we add it to all the nested docs...
|
||||||
|
if (context.docs().size() > 1) {
|
||||||
|
UidField uidField = (UidField) context.rootDoc().getFieldable(UidFieldMapper.NAME);
|
||||||
|
assert uidField != null;
|
||||||
|
// we need to go over the docs and add it...
|
||||||
|
for (int i = 1; i < context.docs().size(); i++) {
|
||||||
|
// we don't need to add it as a full uid field in nested docs, since we don't need versioning
|
||||||
|
context.docs().get(i).add(new Field(UidFieldMapper.NAME, uidField.uid(), Field.Store.NO, Field.Index.NOT_ANALYZED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void parse(ParseContext context) throws IOException {
|
||||||
|
// nothing to do here, we either do it in post parse, or in pre parse.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void validate(ParseContext context) throws MapperParsingException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean includeInObject() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
|
||||||
context.uid(Uid.createUid(context.stringBuilder(), context.type(), context.id()));
|
context.uid(Uid.createUid(context.stringBuilder(), context.type(), context.id()));
|
||||||
// so, caching uid stream and field is fine
|
// so, caching uid stream and field is fine
|
||||||
// since we don't do any mapping parsing without immediate indexing
|
// since we don't do any mapping parsing without immediate indexing
|
||||||
|
|
|
@ -389,7 +389,7 @@ public class ObjectMapper implements Mapper, AllFieldMapper.IncludeInAll {
|
||||||
if (nested.isNested()) {
|
if (nested.isNested()) {
|
||||||
Document nestedDoc = new Document();
|
Document nestedDoc = new Document();
|
||||||
// pre add the uid field if possible (id was already provided)
|
// pre add the uid field if possible (id was already provided)
|
||||||
Fieldable uidField = (Fieldable) context.doc().getFieldable(UidFieldMapper.NAME);
|
Fieldable uidField = context.doc().getFieldable(UidFieldMapper.NAME);
|
||||||
if (uidField != null) {
|
if (uidField != null) {
|
||||||
// we don't need to add it as a full uid field in nested docs, since we don't need versioning
|
// we don't need to add it as a full uid field in nested docs, since we don't need versioning
|
||||||
// we also rely on this for UidField#loadVersion
|
// we also rely on this for UidField#loadVersion
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elastic Search and Shay Banon under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. Elastic Search 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.id;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
|
import org.elasticsearch.index.mapper.DocumentMapper;
|
||||||
|
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||||
|
import org.elasticsearch.index.mapper.MapperTests;
|
||||||
|
import org.elasticsearch.index.mapper.ParsedDocument;
|
||||||
|
import org.elasticsearch.index.mapper.internal.IdFieldMapper;
|
||||||
|
import org.elasticsearch.index.mapper.internal.UidFieldMapper;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public class IdMappingTests {
|
||||||
|
|
||||||
|
@Test public void simpleIdTests() throws Exception {
|
||||||
|
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
|
.endObject().endObject().string();
|
||||||
|
DocumentMapper docMapper = MapperTests.newParser().parse(mapping);
|
||||||
|
|
||||||
|
ParsedDocument doc = docMapper.parse("type", "1", XContentFactory.jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.endObject()
|
||||||
|
.copiedBytes());
|
||||||
|
|
||||||
|
assertThat(doc.rootDoc().get(UidFieldMapper.NAME), notNullValue());
|
||||||
|
assertThat(doc.rootDoc().get(IdFieldMapper.NAME), nullValue());
|
||||||
|
|
||||||
|
try {
|
||||||
|
docMapper.parse("type", null, XContentFactory.jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.endObject()
|
||||||
|
.copiedBytes());
|
||||||
|
assert false;
|
||||||
|
} catch (MapperParsingException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
doc = docMapper.parse("type", null, XContentFactory.jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.field("_id", 1)
|
||||||
|
.endObject()
|
||||||
|
.copiedBytes());
|
||||||
|
|
||||||
|
assertThat(doc.rootDoc().get(UidFieldMapper.NAME), notNullValue());
|
||||||
|
assertThat(doc.rootDoc().get(IdFieldMapper.NAME), nullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testIdIndexed() throws Exception {
|
||||||
|
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||||
|
.startObject("_id").field("index", "not_analyzed").endObject()
|
||||||
|
.endObject().endObject().string();
|
||||||
|
DocumentMapper docMapper = MapperTests.newParser().parse(mapping);
|
||||||
|
|
||||||
|
ParsedDocument doc = docMapper.parse("type", "1", XContentFactory.jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.endObject()
|
||||||
|
.copiedBytes());
|
||||||
|
|
||||||
|
assertThat(doc.rootDoc().get(UidFieldMapper.NAME), notNullValue());
|
||||||
|
assertThat(doc.rootDoc().get(IdFieldMapper.NAME), notNullValue());
|
||||||
|
|
||||||
|
doc = docMapper.parse("type", null, XContentFactory.jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.field("_id", 1)
|
||||||
|
.endObject()
|
||||||
|
.copiedBytes());
|
||||||
|
|
||||||
|
assertThat(doc.rootDoc().get(UidFieldMapper.NAME), notNullValue());
|
||||||
|
assertThat(doc.rootDoc().get(IdFieldMapper.NAME), notNullValue());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue