@Override public Y build(BuilderContext context) { ContentPath.Type origPathType = context.path().pathType(); context.path().pathType(pathType); context.path().add(name); Map<String, Mapper> mappers = new HashMap<String, Mapper>(); for (Mapper.Builder builder : mappersBuilders) { Mapper mapper = builder.build(context); mappers.put(mapper.name(), mapper); } context.path().pathType(origPathType); context.path().remove(); ObjectMapper objectMapper = createMapper( name, context.path().fullPathAsText(name), enabled, nested, dynamic, pathType, mappers); objectMapper.includeInAllIfNotSet(includeInAll); return (Y) objectMapper; }
public ObjectMapper putMapper(Mapper mapper) { if (mapper instanceof AllFieldMapper.IncludeInAll) { ((AllFieldMapper.IncludeInAll) mapper).includeInAllIfNotSet(includeInAll); } synchronized (mutex) { mappers = newMapBuilder(mappers).put(mapper.name(), mapper).immutableMap(); } return this; }
public ObjectMapper putMapper(Mapper mapper) { if (mapper instanceof AllFieldMapper.IncludeInAll) { ((AllFieldMapper.IncludeInAll) mapper).includeInAllIfNotSet(includeInAll); } synchronized (mutex) { mappers = mappers.copyAndPut(mapper.name(), mapper); } return this; }
public ObjectMapper putMapper(Mapper mapper) { if (mapper instanceof AllFieldMapper.IncludeInAll) { ((AllFieldMapper.IncludeInAll) mapper).includeInAllIfNotSet(includeInAll); } synchronized (mutex) { UpdateInPlaceMap<String, Mapper>.Mutator mappingMutator = this.mappers.mutator(); mappingMutator.put(mapper.name(), mapper); mappingMutator.close(); } return this; }
@Override public void merge(final Mapper mergeWith, final MergeResult mergeResult) throws MergeMappingException { if (!(mergeWith instanceof ObjectMapper)) { mergeResult.addConflict( "Can't merge a non object mapping [" + mergeWith.name() + "] with an object mapping [" + name() + "]"); return; } ObjectMapper mergeWithObject = (ObjectMapper) mergeWith; if (nested().isNested()) { if (!mergeWithObject.nested().isNested()) { mergeResult.addConflict( "object mapping [" + name() + "] can't be changed from nested to non-nested"); return; } } else { if (mergeWithObject.nested().isNested()) { mergeResult.addConflict( "object mapping [" + name() + "] can't be changed from non-nested to nested"); return; } } if (!mergeResult.simulate()) { if (mergeWithObject.dynamic != null) { this.dynamic = mergeWithObject.dynamic; } } doMerge(mergeWithObject, mergeResult); List<Mapper> mappersToPut = new ArrayList<>(); List<ObjectMapper> newObjectMappers = new ArrayList<>(); List<FieldMapper> newFieldMappers = new ArrayList<>(); for (Mapper mapper : mergeWithObject) { Mapper mergeWithMapper = mapper; Mapper mergeIntoMapper = mappers.get(mergeWithMapper.simpleName()); if (mergeIntoMapper == null) { // no mapping, simply add it if not simulating if (!mergeResult.simulate()) { mappersToPut.add(mergeWithMapper); MapperUtils.collect(mergeWithMapper, newObjectMappers, newFieldMappers); } } else if (mergeIntoMapper instanceof MetadataFieldMapper == false) { // root mappers can only exist here for backcompat, and are merged in Mapping mergeIntoMapper.merge(mergeWithMapper, mergeResult); } } if (!newFieldMappers.isEmpty()) { mergeResult.addFieldMappers(newFieldMappers); } if (!newObjectMappers.isEmpty()) { mergeResult.addObjectMappers(newObjectMappers); } // add the mappers only after the administration have been done, so it will not be visible to // parser (which first try to read with no lock) for (Mapper mapper : mappersToPut) { putMapper(mapper); } }
public void toXContent( XContentBuilder builder, Params params, ToXContent custom, Mapper... additionalMappers) throws IOException { builder.startObject(name); if (nested.isNested()) { builder.field("type", NESTED_CONTENT_TYPE); if (nested.isIncludeInParent()) { builder.field("include_in_parent", true); } if (nested.isIncludeInRoot()) { builder.field("include_in_root", true); } } else if (mappers .isEmpty()) { // only write the object content type if there are no properties, otherwise, // it is automatically detected builder.field("type", CONTENT_TYPE); } // grr, ugly! on root, dynamic defaults to TRUE, on children, it defaults to null to // inherit the root behavior if (this instanceof RootObjectMapper) { if (dynamic != Dynamic.TRUE) { builder.field("dynamic", dynamic.name().toLowerCase()); } } else { if (dynamic != Defaults.DYNAMIC) { builder.field("dynamic", dynamic.name().toLowerCase()); } } if (enabled != Defaults.ENABLED) { builder.field("enabled", enabled); } if (pathType != Defaults.PATH_TYPE) { builder.field("path", pathType.name().toLowerCase()); } if (includeInAll != null) { builder.field("include_in_all", includeInAll); } if (custom != null) { custom.toXContent(builder, params); } doXContent(builder, params); // sort the mappers so we get consistent serialization format TreeMap<String, Mapper> sortedMappers = new TreeMap<String, Mapper>(mappers); // check internal mappers first (this is only relevant for root object) for (Mapper mapper : sortedMappers.values()) { if (mapper instanceof InternalMapper) { mapper.toXContent(builder, params); } } if (additionalMappers != null && additionalMappers.length > 0) { TreeMap<String, Mapper> additionalSortedMappers = new TreeMap<String, Mapper>(); for (Mapper mapper : additionalMappers) { additionalSortedMappers.put(mapper.name(), mapper); } for (Mapper mapper : additionalSortedMappers.values()) { mapper.toXContent(builder, params); } } if (!mappers.isEmpty()) { builder.startObject("properties"); for (Mapper mapper : sortedMappers.values()) { if (!(mapper instanceof InternalMapper)) { mapper.toXContent(builder, params); } } builder.endObject(); } builder.endObject(); }
@Override public void merge(final Mapper mergeWith, final MergeContext mergeContext) throws MergeMappingException { if (!(mergeWith instanceof ObjectMapper)) { mergeContext.addConflict( "Can't merge a non object mapping [" + mergeWith.name() + "] with an object mapping [" + name() + "]"); return; } ObjectMapper mergeWithObject = (ObjectMapper) mergeWith; if (nested().isNested()) { if (!mergeWithObject.nested().isNested()) { mergeContext.addConflict( "object mapping [" + name() + "] can't be changed from nested to non-nested"); return; } } else { if (mergeWithObject.nested().isNested()) { mergeContext.addConflict( "object mapping [" + name() + "] can't be changed from non-nested to nested"); return; } } doMerge(mergeWithObject, mergeContext); List<Mapper> mappersToTraverse = new ArrayList<Mapper>(); synchronized (mutex) { for (Mapper mergeWithMapper : mergeWithObject.mappers.values()) { Mapper mergeIntoMapper = mappers.get(mergeWithMapper.name()); if (mergeIntoMapper == null) { // no mapping, simply add it if not simulating if (!mergeContext.mergeFlags().simulate()) { putMapper(mergeWithMapper); mappersToTraverse.add(mergeWithMapper); } } else { if ((mergeWithMapper instanceof MultiFieldMapper) && !(mergeIntoMapper instanceof MultiFieldMapper)) { MultiFieldMapper mergeWithMultiField = (MultiFieldMapper) mergeWithMapper; mergeWithMultiField.merge(mergeIntoMapper, mergeContext); if (!mergeContext.mergeFlags().simulate()) { putMapper(mergeWithMultiField); // now, record mappers to traverse events for all mappers for (Mapper mapper : mergeWithMultiField.mappers().values()) { mappersToTraverse.add(mapper); } } } else { mergeIntoMapper.merge(mergeWithMapper, mergeContext); } } } } // call this outside of the mutex for (Mapper mapper : mappersToTraverse) { mapper.traverse(mergeContext.newFieldMappers()); mapper.traverse(mergeContext.newObjectMappers()); } }
public void testReuseExistingMappings() throws IOException, Exception { IndexService indexService = createIndex( "test", Settings.EMPTY, "type", "my_field1", "type=text,store=true", "my_field2", "type=integer,store=false", "my_field3", "type=long,doc_values=false", "my_field4", "type=float,index=false", "my_field5", "type=double,store=true", "my_field6", "type=date,doc_values=false", "my_field7", "type=boolean,doc_values=false"); // Even if the dynamic type of our new field is long, we already have a mapping for the same // field // of type string so it should be mapped as a string DocumentMapper newMapper = indexService.mapperService().documentMapperWithAutoCreate("type2").getDocumentMapper(); Mapper update = parse( newMapper, indexService.mapperService().documentMapperParser(), XContentFactory.jsonBuilder() .startObject() .field("my_field1", 42) .field("my_field2", 43) .field("my_field3", 44) .field("my_field4", 45) .field("my_field5", 46) .field("my_field6", 47) .field("my_field7", true) .endObject()); Mapper myField1Mapper = null; Mapper myField2Mapper = null; Mapper myField3Mapper = null; Mapper myField4Mapper = null; Mapper myField5Mapper = null; Mapper myField6Mapper = null; Mapper myField7Mapper = null; for (Mapper m : update) { switch (m.name()) { case "my_field1": myField1Mapper = m; break; case "my_field2": myField2Mapper = m; break; case "my_field3": myField3Mapper = m; break; case "my_field4": myField4Mapper = m; break; case "my_field5": myField5Mapper = m; break; case "my_field6": myField6Mapper = m; break; case "my_field7": myField7Mapper = m; break; } } assertNotNull(myField1Mapper); // same type assertTrue(myField1Mapper instanceof TextFieldMapper); // and same option assertTrue(((TextFieldMapper) myField1Mapper).fieldType().stored()); // Even if dynamic mappings would map a numeric field as a long, here it should map it as a // integer // since we already have a mapping of type integer assertNotNull(myField2Mapper); // same type assertEquals("integer", ((FieldMapper) myField2Mapper).fieldType().typeName()); // and same option assertFalse(((FieldMapper) myField2Mapper).fieldType().stored()); assertNotNull(myField3Mapper); assertTrue(myField3Mapper instanceof NumberFieldMapper); assertFalse( ((NumberFieldType) ((NumberFieldMapper) myField3Mapper).fieldType()).hasDocValues()); assertNotNull(myField4Mapper); assertTrue(myField4Mapper instanceof NumberFieldMapper); assertEquals(IndexOptions.NONE, ((FieldMapper) myField4Mapper).fieldType().indexOptions()); assertNotNull(myField5Mapper); assertTrue(myField5Mapper instanceof NumberFieldMapper); assertTrue(((NumberFieldMapper) myField5Mapper).fieldType().stored()); assertNotNull(myField6Mapper); assertTrue(myField6Mapper instanceof DateFieldMapper); assertFalse(((DateFieldType) ((DateFieldMapper) myField6Mapper).fieldType()).hasDocValues()); assertNotNull(myField7Mapper); assertTrue(myField7Mapper instanceof BooleanFieldMapper); assertFalse( ((BooleanFieldType) ((BooleanFieldMapper) myField7Mapper).fieldType()).hasDocValues()); // This can't work try { parse( newMapper, indexService.mapperService().documentMapperParser(), XContentFactory.jsonBuilder().startObject().field("my_field2", "foobar").endObject()); fail("Cannot succeed, incompatible types"); } catch (MapperParsingException e) { // expected } }
public void toXContent( XContentBuilder builder, Params params, ToXContent custom, Mapper... additionalMappers) throws IOException { builder.startObject(name); if (nested.isNested()) { builder.field("type", NESTED_CONTENT_TYPE); if (nested.isIncludeInParent()) { builder.field("include_in_parent", true); } if (nested.isIncludeInRoot()) { builder.field("include_in_root", true); } } else if (mappers .isEmpty()) { // only write the object content type if there are no properties, otherwise, // it is automatically detected builder.field("type", CONTENT_TYPE); } if (dynamic != null) { builder.field("dynamic", dynamic.name().toLowerCase(Locale.ROOT)); } if (enabled != Defaults.ENABLED) { builder.field("enabled", enabled); } if (pathType != Defaults.PATH_TYPE) { builder.field("path", pathType.name().toLowerCase(Locale.ROOT)); } if (includeInAll != null) { builder.field("include_in_all", includeInAll); } if (custom != null) { custom.toXContent(builder, params); } doXContent(builder, params); // sort the mappers so we get consistent serialization format Mapper[] sortedMappers = Iterables.toArray(mappers.values(), Mapper.class); Arrays.sort( sortedMappers, new Comparator<Mapper>() { @Override public int compare(Mapper o1, Mapper o2) { return o1.name().compareTo(o2.name()); } }); // check internal mappers first (this is only relevant for root object) for (Mapper mapper : sortedMappers) { if (mapper instanceof InternalMapper) { mapper.toXContent(builder, params); } } if (additionalMappers != null && additionalMappers.length > 0) { TreeMap<String, Mapper> additionalSortedMappers = new TreeMap<>(); for (Mapper mapper : additionalMappers) { additionalSortedMappers.put(mapper.name(), mapper); } for (Mapper mapper : additionalSortedMappers.values()) { mapper.toXContent(builder, params); } } if (!mappers.isEmpty()) { builder.startObject("properties"); for (Mapper mapper : sortedMappers) { if (!(mapper instanceof InternalMapper)) { mapper.toXContent(builder, params); } } builder.endObject(); } builder.endObject(); }
@Override public void merge(final Mapper mergeWith, final MergeContext mergeContext) throws MergeMappingException { if (!(mergeWith instanceof ObjectMapper)) { mergeContext.addConflict( "Can't merge a non object mapping [" + mergeWith.name() + "] with an object mapping [" + name() + "]"); return; } ObjectMapper mergeWithObject = (ObjectMapper) mergeWith; if (nested().isNested()) { if (!mergeWithObject.nested().isNested()) { mergeContext.addConflict( "object mapping [" + name() + "] can't be changed from nested to non-nested"); return; } } else { if (mergeWithObject.nested().isNested()) { mergeContext.addConflict( "object mapping [" + name() + "] can't be changed from non-nested to nested"); return; } } if (!mergeContext.mergeFlags().simulate()) { if (mergeWithObject.dynamic != null) { this.dynamic = mergeWithObject.dynamic; } } doMerge(mergeWithObject, mergeContext); List<Mapper> mappersToPut = new ArrayList<>(); FieldMapperListener.Aggregator newFieldMappers = new FieldMapperListener.Aggregator(); ObjectMapperListener.Aggregator newObjectMappers = new ObjectMapperListener.Aggregator(); synchronized (mutex) { for (Mapper mapper : mergeWithObject.mappers.values()) { Mapper mergeWithMapper = mapper; Mapper mergeIntoMapper = mappers.get(mergeWithMapper.name()); if (mergeIntoMapper == null) { // no mapping, simply add it if not simulating if (!mergeContext.mergeFlags().simulate()) { mappersToPut.add(mergeWithMapper); mergeWithMapper.traverse(newFieldMappers); mergeWithMapper.traverse(newObjectMappers); } } else { mergeIntoMapper.merge(mergeWithMapper, mergeContext); } } if (!newFieldMappers.mappers.isEmpty()) { mergeContext.docMapper().addFieldMappers(newFieldMappers.mappers); } if (!newObjectMappers.mappers.isEmpty()) { mergeContext.docMapper().addObjectMappers(newObjectMappers.mappers); } // and the mappers only after the administration have been done, so it will not be visible to // parser (which first try to read with no lock) for (Mapper mapper : mappersToPut) { putMapper(mapper); } } }