@Override public void postDeleteUnderLock(Engine.Delete delete) { // remove the query under a lock if (PercolatorService.TYPE_NAME.equals(delete.type())) { removePercolateQuery(delete.id()); } }
// never expose this to the outside world, we need to reparse the doc mapper so we get fresh // instances of field mappers to properly remove existing doc mapper private DocumentMapper merge(DocumentMapper mapper) { synchronized (typeMutex) { if (mapper.type().length() == 0) { throw new InvalidTypeNameException("mapping type name is empty"); } if (mapper.type().charAt(0) == '_' && !PercolatorService.TYPE_NAME.equals(mapper.type())) { throw new InvalidTypeNameException( "mapping type name [" + mapper.type() + "] can't start with '_'"); } if (mapper.type().contains("#")) { throw new InvalidTypeNameException( "mapping type name [" + mapper.type() + "] should not include '#' in it"); } if (mapper.type().contains(",")) { throw new InvalidTypeNameException( "mapping type name [" + mapper.type() + "] should not include ',' in it"); } if (mapper.type().contains(".")) { logger.warn( "Type [{}] contains a '.', it is recommended not to include it within a type name", mapper.type()); } // we can add new field/object mappers while the old ones are there // since we get new instances of those, and when we remove, we remove // by instance equality DocumentMapper oldMapper = mappers.get(mapper.type()); if (oldMapper != null) { DocumentMapper.MergeResult result = oldMapper.merge(mapper, mergeFlags().simulate(false)); if (result.hasConflicts()) { // TODO: What should we do??? if (logger.isDebugEnabled()) { logger.debug( "merging mapping for type [{}] resulted in conflicts: [{}]", mapper.type(), Arrays.toString(result.conflicts())); } } return oldMapper; } else { FieldMapperListener.Aggregator fieldMappersAgg = new FieldMapperListener.Aggregator(); mapper.traverse(fieldMappersAgg); addFieldMappers( fieldMappersAgg.mappers.toArray(new FieldMapper[fieldMappersAgg.mappers.size()])); mapper.addFieldMapperListener(fieldMapperListener, false); ObjectMapperListener.Aggregator objectMappersAgg = new ObjectMapperListener.Aggregator(); mapper.traverse(objectMappersAgg); addObjectMappers( objectMappersAgg.mappers.toArray(new ObjectMapper[objectMappersAgg.mappers.size()])); mapper.addObjectMapperListener(objectMapperListener, false); mappers = newMapBuilder(mappers).put(mapper.type(), mapper).map(); for (DocumentTypeListener typeListener : typeListeners) { typeListener.created(mapper.type()); } return mapper; } } }
@Override public void postIndexUnderLock(Engine.Index index) { // add the query under a doc lock if (PercolatorService.TYPE_NAME.equals(index.type())) { addPercolateQuery(index.id(), index.source()); } }
@Override public void postCreateUnderLock(Engine.Create create) { // add the query under a doc lock if (PercolatorService.TYPE_NAME.equals(create.type())) { addPercolateQuery(create.id(), create.source()); } }
@Override public void afterRemove(DocumentMapper mapper) { if (PercolatorService.TYPE_NAME.equals(mapper.type())) { disableRealTimePercolator(); clear(); } }
@Override public Engine.Index preIndex(Engine.Index index) { // validate the query here, before we index if (PercolatorService.TYPE_NAME.equals(index.type())) { parsePercolatorDocument(index.id(), index.source()); } return index; }
@Override public Engine.Create preCreate(Engine.Create create) { // validate the query here, before we index if (PercolatorService.TYPE_NAME.equals(create.type())) { parsePercolatorDocument(create.id(), create.source()); } return create; }
public DocumentMapper parse(String mappingType, String mappingSource, boolean applyDefault) throws MapperParsingException { String defaultMappingSource; if (PercolatorService.TYPE_NAME.equals(mappingType)) { defaultMappingSource = this.defaultPercolatorMappingSource; } else { defaultMappingSource = this.defaultMappingSource; } return documentParser.parse( mappingType, mappingSource, applyDefault ? defaultMappingSource : null); }
@Override public void beforeCreate(DocumentMapper mapper) { if (PercolatorService.TYPE_NAME.equals(mapper.type())) { enableRealTimePercolator(); } }
/** * A filter for search. If a filter is required, will return it, otherwise, will return * <tt>null</tt>. */ @Nullable public Filter searchFilter(String... types) { boolean filterPercolateType = hasMapping(PercolatorService.TYPE_NAME); if (types != null && filterPercolateType) { for (String type : types) { if (PercolatorService.TYPE_NAME.equals(type)) { filterPercolateType = false; break; } } } Filter excludePercolatorType = null; if (filterPercolateType) { excludePercolatorType = new NotFilter(documentMapper(PercolatorService.TYPE_NAME).typeFilter()); } if (types == null || types.length == 0) { if (hasNested && filterPercolateType) { return new AndFilter(ImmutableList.of(excludePercolatorType, NonNestedDocsFilter.INSTANCE)); } else if (hasNested) { return NonNestedDocsFilter.INSTANCE; } else if (filterPercolateType) { return excludePercolatorType; } else { return null; } } // if we filter by types, we don't need to filter by non nested docs // since they have different types (starting with __) if (types.length == 1) { DocumentMapper docMapper = documentMapper(types[0]); if (docMapper == null) { return new TermFilter(new Term(types[0])); } return docMapper.typeFilter(); } // see if we can use terms filter boolean useTermsFilter = true; for (String type : types) { DocumentMapper docMapper = documentMapper(type); if (docMapper == null) { useTermsFilter = false; break; } if (!docMapper.typeMapper().fieldType().indexed()) { useTermsFilter = false; break; } } if (useTermsFilter) { BytesRef[] typesBytes = new BytesRef[types.length]; for (int i = 0; i < typesBytes.length; i++) { typesBytes[i] = new BytesRef(types[i]); } TermsFilter termsFilter = new TermsFilter(TypeFieldMapper.NAME, typesBytes); if (filterPercolateType) { return new AndFilter(ImmutableList.of(excludePercolatorType, termsFilter)); } else { return termsFilter; } } else { // Current bool filter requires that at least one should clause matches, even with a must // clause. XBooleanFilter bool = new XBooleanFilter(); for (String type : types) { DocumentMapper docMapper = documentMapper(type); if (docMapper == null) { bool.add( new FilterClause( new TermFilter(new Term(TypeFieldMapper.NAME, type)), BooleanClause.Occur.SHOULD)); } else { bool.add(new FilterClause(docMapper.typeFilter(), BooleanClause.Occur.SHOULD)); } } if (filterPercolateType) { bool.add(excludePercolatorType, BooleanClause.Occur.MUST); } return bool; } }
/** * A filter for search. If a filter is required, will return it, otherwise, will return * <tt>null</tt>. */ @Nullable public Query searchFilter(String... types) { boolean filterPercolateType = hasMapping(PercolatorService.TYPE_NAME); if (types != null && filterPercolateType) { for (String type : types) { if (PercolatorService.TYPE_NAME.equals(type)) { filterPercolateType = false; break; } } } Query percolatorType = null; if (filterPercolateType) { percolatorType = documentMapper(PercolatorService.TYPE_NAME).typeFilter(); } if (types == null || types.length == 0) { if (hasNested && filterPercolateType) { BooleanQuery bq = new BooleanQuery(); bq.add(percolatorType, Occur.MUST_NOT); bq.add(Queries.newNonNestedFilter(), Occur.MUST); return new ConstantScoreQuery(bq); } else if (hasNested) { return Queries.newNonNestedFilter(); } else if (filterPercolateType) { return new ConstantScoreQuery(Queries.not(percolatorType)); } else { return null; } } // if we filter by types, we don't need to filter by non nested docs // since they have different types (starting with __) if (types.length == 1) { DocumentMapper docMapper = documentMapper(types[0]); Query filter = docMapper != null ? docMapper.typeFilter() : new TermQuery(new Term(TypeFieldMapper.NAME, types[0])); if (filterPercolateType) { BooleanQuery bq = new BooleanQuery(); bq.add(percolatorType, Occur.MUST_NOT); bq.add(filter, Occur.MUST); return new ConstantScoreQuery(bq); } else { return filter; } } // see if we can use terms filter boolean useTermsFilter = true; for (String type : types) { DocumentMapper docMapper = documentMapper(type); if (docMapper == null) { useTermsFilter = false; break; } if (docMapper.typeMapper().fieldType().indexOptions() == IndexOptions.NONE) { useTermsFilter = false; break; } } // We only use terms filter is there is a type filter, this means we don't need to check for // hasNested here if (useTermsFilter) { BytesRef[] typesBytes = new BytesRef[types.length]; for (int i = 0; i < typesBytes.length; i++) { typesBytes[i] = new BytesRef(types[i]); } TermsQuery termsFilter = new TermsQuery(TypeFieldMapper.NAME, typesBytes); if (filterPercolateType) { BooleanQuery bq = new BooleanQuery(); bq.add(percolatorType, Occur.MUST_NOT); bq.add(termsFilter, Occur.MUST); return new ConstantScoreQuery(bq); } else { return termsFilter; } } else { // Current bool filter requires that at least one should clause matches, even with a must // clause. BooleanQuery bool = new BooleanQuery(); for (String type : types) { DocumentMapper docMapper = documentMapper(type); if (docMapper == null) { bool.add(new TermQuery(new Term(TypeFieldMapper.NAME, type)), BooleanClause.Occur.SHOULD); } else { bool.add(docMapper.typeFilter(), BooleanClause.Occur.SHOULD); } } if (filterPercolateType) { bool.add(percolatorType, BooleanClause.Occur.MUST_NOT); } if (hasNested) { bool.add(Queries.newNonNestedFilter(), BooleanClause.Occur.MUST); } return new ConstantScoreQuery(bool); } }
private boolean typeNameStartsWithIllegalDot(DocumentMapper mapper) { return mapper.type().startsWith(".") && !PercolatorService.TYPE_NAME.equals(mapper.type()); }