private InternalSearchHit.InternalNestedIdentity getInternalNestedIdentity( SearchContext context, int nestedSubDocId, LeafReaderContext subReaderContext, DocumentMapper documentMapper, ObjectMapper nestedObjectMapper) throws IOException { int currentParent = nestedSubDocId; ObjectMapper nestedParentObjectMapper; ObjectMapper current = nestedObjectMapper; String originalName = nestedObjectMapper.name(); InternalSearchHit.InternalNestedIdentity nestedIdentity = null; do { Query parentFilter; nestedParentObjectMapper = documentMapper.findParentObjectMapper(current); if (nestedParentObjectMapper != null) { if (nestedParentObjectMapper.nested().isNested() == false) { current = nestedParentObjectMapper; continue; } parentFilter = nestedParentObjectMapper.nestedTypeFilter(); } else { parentFilter = Queries.newNonNestedFilter(); } Query childFilter = nestedObjectMapper.nestedTypeFilter(); if (childFilter == null) { current = nestedParentObjectMapper; continue; } final Weight childWeight = context.searcher().createNormalizedWeight(childFilter, false); Scorer childScorer = childWeight.scorer(subReaderContext); if (childScorer == null) { current = nestedParentObjectMapper; continue; } DocIdSetIterator childIter = childScorer.iterator(); BitSet parentBits = context.bitsetFilterCache().getBitSetProducer(parentFilter).getBitSet(subReaderContext); int offset = 0; int nextParent = parentBits.nextSetBit(currentParent); for (int docId = childIter.advance(currentParent + 1); docId < nextParent && docId != DocIdSetIterator.NO_MORE_DOCS; docId = childIter.nextDoc()) { offset++; } currentParent = nextParent; current = nestedObjectMapper = nestedParentObjectMapper; int currentPrefix = current == null ? 0 : current.name().length() + 1; nestedIdentity = new InternalSearchHit.InternalNestedIdentity( originalName.substring(currentPrefix), offset, nestedIdentity); if (current != null) { originalName = current.name(); } } while (current != null); return nestedIdentity; }
@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()); } }
@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); } } }