public synchronized MergeResult merge(DocumentMapper mergeWith, MergeFlags mergeFlags) { MergeContext mergeContext = new MergeContext(this, mergeFlags); rootObjectMapper.merge(mergeWith.rootObjectMapper, mergeContext); for (Map.Entry<Class<? extends RootMapper>, RootMapper> entry : rootMappers.entrySet()) { // root mappers included in root object will get merge in the rootObjectMapper if (entry.getValue().includeInObject()) { continue; } RootMapper mergeWithRootMapper = mergeWith.rootMappers.get(entry.getKey()); if (mergeWithRootMapper != null) { entry.getValue().merge(mergeWithRootMapper, mergeContext); } } if (!mergeFlags.simulate()) { if (!mergeContext.newFieldMappers().mappers.isEmpty()) { addFieldMappers(mergeContext.newFieldMappers().mappers); } if (!mergeContext.newObjectMappers().mappers.isEmpty()) { addObjectMappers(mergeContext.newObjectMappers().mappers); } // let the merge with attributes to override the attributes meta = mergeWith.meta(); // update the source of the merged one refreshSource(); } return new MergeResult(mergeContext.buildConflicts()); }
public void close() { cache.remove(); rootObjectMapper.close(); for (RootMapper rootMapper : rootMappersOrdered) { rootMapper.close(); } }
public void traverse(FieldMapperListener listener) { for (RootMapper rootMapper : rootMappersOrdered) { if (!rootMapper.includeInObject() && rootMapper instanceof FieldMapper) { listener.fieldMapper((FieldMapper) rootMapper); } } rootObjectMapper.traverse(listener); }
@Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { rootObjectMapper.toXContent( builder, params, new ToXContent() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { if (indexAnalyzer != null && searchAnalyzer != null && indexAnalyzer.name().equals(searchAnalyzer.name()) && !indexAnalyzer.name().startsWith("_")) { if (!indexAnalyzer.name().equals("default")) { // same analyzers, output it once builder.field("analyzer", indexAnalyzer.name()); } } else { if (indexAnalyzer != null && !indexAnalyzer.name().startsWith("_")) { if (!indexAnalyzer.name().equals("default")) { builder.field("index_analyzer", indexAnalyzer.name()); } } if (searchAnalyzer != null && !searchAnalyzer.name().startsWith("_")) { if (!searchAnalyzer.name().equals("default")) { builder.field("search_analyzer", searchAnalyzer.name()); } } } if (meta != null && !meta.isEmpty()) { builder.field("_meta", meta()); } return builder; } // no need to pass here id and boost, since they are added to the root object mapper // in the constructor }, rootMappersNotIncludedInObject); return builder; }
public void traverse(ObjectMapperListener listener) { rootObjectMapper.traverse(listener); }
public ParsedDocument parse(SourceToParse source, @Nullable ParseListener listener) throws MapperParsingException { ParseContext context = cache.get(); if (source.type() != null && !source.type().equals(this.type)) { throw new MapperParsingException( "Type mismatch, provide type [" + source.type() + "] but mapper is of type [" + this.type + "]"); } source.type(this.type); XContentParser parser = source.parser(); try { if (parser == null) { parser = XContentHelper.createParser(source.source()); } context.reset(parser, new Document(), source, listener); // on a newly created instance of document mapper, we always consider it as new mappers that // have been added if (initMappersAdded) { context.setMappingsModified(); initMappersAdded = false; } // will result in START_OBJECT int countDownTokens = 0; XContentParser.Token token = parser.nextToken(); if (token != XContentParser.Token.START_OBJECT) { throw new MapperParsingException("Malformed content, must start with an object"); } boolean emptyDoc = false; token = parser.nextToken(); if (token == XContentParser.Token.END_OBJECT) { // empty doc, we can handle it... emptyDoc = true; } else if (token != XContentParser.Token.FIELD_NAME) { throw new MapperParsingException( "Malformed content, after first object, either the type field or the actual properties should exist"); } if (type.equals(parser.currentName())) { // first field is the same as the type, this might be because the type is provided, and the // object exists within it // or because there is a valid field that by chance is named as the type // Note, in this case, we only handle plain value types, an object type will be analyzed as // if it was the type itself // and other same level fields will be ignored token = parser.nextToken(); countDownTokens++; // commented out, allow for same type with START_OBJECT, we do our best to handle it except // for the above corner case // if (token != XContentParser.Token.START_OBJECT) { // throw new MapperException("Malformed content, a field with the same // name as the type must be an object with the properties/fields within it"); // } } for (RootMapper rootMapper : rootMappersOrdered) { rootMapper.preParse(context); } if (!emptyDoc) { rootObjectMapper.parse(context); } for (int i = 0; i < countDownTokens; i++) { parser.nextToken(); } // fire up any new mappers if exists if (!context.newFieldMappers().mappers.isEmpty()) { addFieldMappers(context.newFieldMappers().mappers); context.newFieldMappers().mappers.clear(); } if (!context.newObjectMappers().mappers.isEmpty()) { addObjectMappers(context.newObjectMappers().mappers); context.newObjectMappers().mappers.clear(); } for (RootMapper rootMapper : rootMappersOrdered) { rootMapper.postParse(context); } for (RootMapper rootMapper : rootMappersOrdered) { rootMapper.validate(context); } } catch (Throwable e) { // we have to fire up any new mappers even on a failure, because they // have been added internally to each compound mapper... // ... we have no option to "rollback" a change, which is very tricky in our copy on change // system... if (!context.newFieldMappers().mappers.isEmpty()) { addFieldMappers(context.newFieldMappers().mappers); context.newFieldMappers().mappers.clear(); } if (!context.newObjectMappers().mappers.isEmpty()) { addObjectMappers(context.newObjectMappers().mappers); context.newObjectMappers().mappers.clear(); } // if its already a mapper parsing exception, no need to wrap it... if (e instanceof MapperParsingException) { throw (MapperParsingException) e; } throw new MapperParsingException("failed to parse", e); } finally { // only close the parser when its not provided externally if (source.parser() == null && parser != null) { parser.close(); } } // reverse the order of docs for nested docs support, parent should be last if (context.docs().size() > 1) { Collections.reverse(context.docs()); } // apply doc boost if (context.docBoost() != 1.0f) { Set<String> encounteredFields = Sets.newHashSet(); for (Document doc : context.docs()) { encounteredFields.clear(); for (IndexableField field : doc) { if (field.fieldType().indexed() && !field.fieldType().omitNorms()) { if (!encounteredFields.contains(field.name())) { ((Field) field).setBoost(context.docBoost() * field.boost()); encounteredFields.add(field.name()); } } } } } ParsedDocument doc = new ParsedDocument( context.uid(), context.id(), context.type(), source.routing(), source.timestamp(), source.ttl(), context.docs(), context.analyzer(), context.source(), context.mappingsModified()) .parent(source.parent()); // reset the context to free up memory context.reset(null, null, null, null); return doc; }
public DocumentMapper( String index, @Nullable Settings indexSettings, DocumentMapperParser docMapperParser, RootObjectMapper rootObjectMapper, ImmutableMap<String, Object> meta, NamedAnalyzer indexAnalyzer, NamedAnalyzer searchAnalyzer, NamedAnalyzer searchQuoteAnalyzer, Map<Class<? extends RootMapper>, RootMapper> rootMappers) { this.index = index; this.indexSettings = indexSettings; this.type = rootObjectMapper.name(); this.docMapperParser = docMapperParser; this.meta = meta; this.rootObjectMapper = rootObjectMapper; this.rootMappers = ImmutableMap.copyOf(rootMappers); this.rootMappersOrdered = rootMappers.values().toArray(new RootMapper[rootMappers.values().size()]); List<RootMapper> rootMappersNotIncludedInObjectLst = newArrayList(); for (RootMapper rootMapper : rootMappersOrdered) { if (!rootMapper.includeInObject()) { rootMappersNotIncludedInObjectLst.add(rootMapper); } } this.rootMappersNotIncludedInObject = rootMappersNotIncludedInObjectLst.toArray( new RootMapper[rootMappersNotIncludedInObjectLst.size()]); this.indexAnalyzer = indexAnalyzer; this.searchAnalyzer = searchAnalyzer; this.searchQuoteAnalyzer = searchQuoteAnalyzer != null ? searchQuoteAnalyzer : searchAnalyzer; this.typeFilter = typeMapper().termFilter(type, null); if (rootMapper(ParentFieldMapper.class) != null) { // mark the routing field mapper as required rootMapper(RoutingFieldMapper.class).markAsRequired(); } FieldMapperListener.Aggregator fieldMappersAgg = new FieldMapperListener.Aggregator(); for (RootMapper rootMapper : rootMappersOrdered) { if (rootMapper.includeInObject()) { rootObjectMapper.putMapper(rootMapper); } else { if (rootMapper instanceof FieldMapper) { fieldMappersAgg.mappers.add((FieldMapper) rootMapper); } } } // now traverse and get all the statically defined ones rootObjectMapper.traverse(fieldMappersAgg); this.fieldMappers = new DocumentFieldMappers(this, fieldMappersAgg.mappers); final Map<String, ObjectMapper> objectMappers = Maps.newHashMap(); rootObjectMapper.traverse( new ObjectMapperListener() { @Override public void objectMapper(ObjectMapper objectMapper) { objectMappers.put(objectMapper.fullPath(), objectMapper); } }); this.objectMappers = ImmutableMap.copyOf(objectMappers); for (ObjectMapper objectMapper : objectMappers.values()) { if (objectMapper.nested().isNested()) { hasNestedObjects = true; } } refreshSource(); }
public DocumentMapper( MapperService mapperService, String index, @Nullable Settings indexSettings, DocumentMapperParser docMapperParser, RootObjectMapper rootObjectMapper, ImmutableMap<String, Object> meta, Map<Class<? extends MetadataFieldMapper>, MetadataFieldMapper> rootMappers, List<SourceTransform> sourceTransforms, ReentrantReadWriteLock mappingLock) { this.mapperService = mapperService; this.type = rootObjectMapper.name(); this.typeText = new StringAndBytesText(this.type); this.mapping = new Mapping( Version.indexCreated(indexSettings), rootObjectMapper, rootMappers.values().toArray(new MetadataFieldMapper[rootMappers.values().size()]), sourceTransforms.toArray(new SourceTransform[sourceTransforms.size()]), meta); this.documentParser = new DocumentParser( index, indexSettings, docMapperParser, this, new ReleasableLock(mappingLock.readLock())); this.typeFilter = typeMapper().fieldType().termQuery(type, null); this.mappingWriteLock = new ReleasableLock(mappingLock.writeLock()); this.mappingLock = mappingLock; if (rootMapper(ParentFieldMapper.class).active()) { // mark the routing field mapper as required rootMapper(RoutingFieldMapper.class).markAsRequired(); } // collect all the mappers for this type List<ObjectMapper> newObjectMappers = new ArrayList<>(); List<FieldMapper> newFieldMappers = new ArrayList<>(); for (MetadataFieldMapper metadataMapper : this.mapping.metadataMappers) { if (metadataMapper instanceof FieldMapper) { newFieldMappers.add((FieldMapper) metadataMapper); } } MapperUtils.collect(this.mapping.root, newObjectMappers, newFieldMappers); this.fieldMappers = new DocumentFieldMappers(docMapperParser.analysisService).copyAndAllAll(newFieldMappers); this.objectMappers = Maps.uniqueIndex( newObjectMappers, new Function<ObjectMapper, String>() { @Override public String apply(ObjectMapper mapper) { return mapper.fullPath(); } }); for (ObjectMapper objectMapper : newObjectMappers) { if (objectMapper.nested().isNested()) { hasNestedObjects = true; } } refreshSource(); }