diff options
author | Martijn van Groningen <martijn.v.groningen@gmail.com> | 2017-06-02 14:34:20 +0200 |
---|---|---|
committer | Martijn van Groningen <martijn.v.groningen@gmail.com> | 2017-06-02 23:27:16 +0200 |
commit | 2a71a7bffc7ad1262cdf84554277653858c3b7f5 (patch) | |
tree | 8f10bfd683b66699a0a91aa1f7e869436d4eceb9 /modules/parent-join/src/main/java/org | |
parent | a32d1b91fa44c005ea41fa17323ea6bc65352092 (diff) |
Change `has_child`, `has_parent` queries and `childen` aggregation to work with the new join field type and
at the same time maintaining support for the `_parent` meta field type.
Relates to #20257
Diffstat (limited to 'modules/parent-join/src/main/java/org')
6 files changed, 133 insertions, 23 deletions
diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java index 35dc4eacbf..3560736e44 100644 --- a/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java +++ b/modules/parent-join/src/main/java/org/elasticsearch/join/aggregations/ChildrenAggregationBuilder.java @@ -30,6 +30,8 @@ import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.ParentFieldMapper; import org.elasticsearch.index.query.QueryParseContext; +import org.elasticsearch.join.mapper.ParentIdFieldMapper; +import org.elasticsearch.join.mapper.ParentJoinFieldMapper; import org.elasticsearch.search.aggregations.AggregatorFactories.Builder; import org.elasticsearch.search.aggregations.AggregatorFactory; import org.elasticsearch.search.aggregations.support.FieldContext; @@ -92,8 +94,30 @@ public class ChildrenAggregationBuilder @Override protected ValuesSourceConfig<WithOrdinals> resolveConfig(SearchContext context) { ValuesSourceConfig<WithOrdinals> config = new ValuesSourceConfig<>(ValuesSourceType.BYTES); - DocumentMapper childDocMapper = context.mapperService().documentMapper(childType); + if (context.mapperService().getIndexSettings().isSingleType()) { + joinFieldResolveConfig(context, config); + } else { + parentFieldResolveConfig(context, config); + } + return config; + } + + private void joinFieldResolveConfig(SearchContext context, ValuesSourceConfig<WithOrdinals> config) { + ParentJoinFieldMapper parentJoinFieldMapper = ParentJoinFieldMapper.getMapper(context.mapperService()); + ParentIdFieldMapper parentIdFieldMapper = parentJoinFieldMapper.getParentIdFieldMapper(childType, false); + if (parentIdFieldMapper != null) { + parentFilter = parentIdFieldMapper.getParentFilter(); + childFilter = parentIdFieldMapper.getChildFilter(childType); + MappedFieldType fieldType = parentIdFieldMapper.fieldType(); + final SortedSetDVOrdinalsIndexFieldData fieldData = context.fieldData().getForField(fieldType); + config.fieldContext(new FieldContext(fieldType.name(), fieldData, fieldType)); + } else { + config.unmapped(true); + } + } + private void parentFieldResolveConfig(SearchContext context, ValuesSourceConfig<WithOrdinals> config) { + DocumentMapper childDocMapper = context.mapperService().documentMapper(childType); if (childDocMapper != null) { ParentFieldMapper parentFieldMapper = childDocMapper.parentFieldMapper(); if (!parentFieldMapper.active()) { @@ -107,14 +131,13 @@ public class ChildrenAggregationBuilder MappedFieldType parentFieldType = parentDocMapper.parentFieldMapper().getParentJoinFieldType(); final SortedSetDVOrdinalsIndexFieldData fieldData = context.fieldData().getForField(parentFieldType); config.fieldContext(new FieldContext(parentFieldType.name(), fieldData, - parentFieldType)); + parentFieldType)); } else { config.unmapped(true); } } else { config.unmapped(true); } - return config; } @Override diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java index 43608e9b54..db9fae9b47 100644 --- a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java +++ b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java @@ -40,7 +40,7 @@ import java.util.List; * This class is also used to quickly retrieve the parent-join field defined in a mapping without * specifying the name of the field. */ -class MetaJoinFieldMapper extends FieldMapper { +public class MetaJoinFieldMapper extends FieldMapper { static final String NAME = "_parent_join"; static final String CONTENT_TYPE = "parent_join"; @@ -68,8 +68,9 @@ class MetaJoinFieldMapper extends FieldMapper { } } - static final class MetaJoinFieldType extends StringFieldType { - ParentJoinFieldMapper mapper; + public static class MetaJoinFieldType extends StringFieldType { + + private ParentJoinFieldMapper mapper; MetaJoinFieldType() {} @@ -100,6 +101,10 @@ class MetaJoinFieldMapper extends FieldMapper { BytesRef binaryValue = (BytesRef) value; return binaryValue.utf8ToString(); } + + public ParentJoinFieldMapper getMapper() { + return mapper; + } } MetaJoinFieldMapper(String name, MappedFieldType fieldType, Settings indexSettings) { diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java index 7a042eae84..cc2815c373 100644 --- a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java +++ b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java @@ -23,6 +23,12 @@ import org.apache.lucene.document.Field; import org.apache.lucene.document.SortedDocValuesField; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexableField; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.ConstantScoreQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.settings.Settings; @@ -47,7 +53,7 @@ public final class ParentIdFieldMapper extends FieldMapper { static final String CONTENT_TYPE = "parent"; static class Defaults { - public static final MappedFieldType FIELD_TYPE = new ParentIdFieldType(); + static final MappedFieldType FIELD_TYPE = new ParentIdFieldType(); static { FIELD_TYPE.setTokenized(false); @@ -86,7 +92,7 @@ public final class ParentIdFieldMapper extends FieldMapper { } public static final class ParentIdFieldType extends StringFieldType { - public ParentIdFieldType() { + ParentIdFieldType() { setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); } @@ -145,6 +151,9 @@ public final class ParentIdFieldMapper extends FieldMapper { return parentName; } + public Query getParentFilter() { + return new TermQuery(new Term(name().substring(0, name().indexOf('#')), parentName)); + } /** * Returns the children names associated with this mapper. */ @@ -152,6 +161,18 @@ public final class ParentIdFieldMapper extends FieldMapper { return children; } + public Query getChildFilter(String type) { + return new TermQuery(new Term(name().substring(0, name().indexOf('#')), type)); + } + + public Query getChildrenFilter() { + BooleanQuery.Builder builder = new BooleanQuery.Builder(); + for (String child : children) { + builder.add(getChildFilter(child), BooleanClause.Occur.SHOULD); + } + return new ConstantScoreQuery(builder.build()); + } + @Override protected void parseCreateField(ParseContext context, List<IndexableField> fields) throws IOException { if (context.externalValueSet() == false) { diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java index d9c12d85c1..ecabbb096e 100644 --- a/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java +++ b/modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java @@ -81,7 +81,7 @@ public final class ParentJoinFieldMapper extends FieldMapper { public static ParentJoinFieldMapper getMapper(MapperService service) { MetaJoinFieldMapper.MetaJoinFieldType fieldType = (MetaJoinFieldMapper.MetaJoinFieldType) service.fullName(MetaJoinFieldMapper.NAME); - return fieldType == null ? null : fieldType.mapper; + return fieldType == null ? null : fieldType.getMapper(); } private static String getParentIdFieldName(String joinFieldName, String parentName) { @@ -121,11 +121,11 @@ public final class ParentJoinFieldMapper extends FieldMapper { } } - static class Builder extends FieldMapper.Builder<Builder, ParentJoinFieldMapper> { + public static class Builder extends FieldMapper.Builder<Builder, ParentJoinFieldMapper> { final List<ParentIdFieldMapper.Builder> parentIdFieldBuilders = new ArrayList<>(); boolean eagerGlobalOrdinals = true; - Builder(String name) { + public Builder(String name) { super(name, Defaults.FIELD_TYPE, Defaults.FIELD_TYPE); builder = this; } @@ -431,4 +431,5 @@ public final class ParentJoinFieldMapper extends FieldMapper { } } } + } diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java index f574236b35..6485b8f649 100644 --- a/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java +++ b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java @@ -49,6 +49,8 @@ import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryRewriteContext; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardException; +import org.elasticsearch.join.mapper.ParentIdFieldMapper; +import org.elasticsearch.join.mapper.ParentJoinFieldMapper; import java.io.IOException; import java.util.HashMap; @@ -305,6 +307,34 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil @Override protected Query doToQuery(QueryShardContext context) throws IOException { + if (context.getIndexSettings().isSingleType()) { + return joinFieldDoToQuery(context); + } else { + return parentFieldDoToQuery(context); + } + } + + private Query joinFieldDoToQuery(QueryShardContext context) throws IOException { + ParentJoinFieldMapper joinFieldMapper = ParentJoinFieldMapper.getMapper(context.getMapperService()); + ParentIdFieldMapper parentIdFieldMapper = joinFieldMapper.getParentIdFieldMapper(type, false); + if (parentIdFieldMapper != null) { + Query parentFilter = parentIdFieldMapper.getParentFilter(); + Query childFilter = parentIdFieldMapper.getChildFilter(type); + Query innerQuery = Queries.filtered(query.toQuery(context), childFilter); + MappedFieldType fieldType = parentIdFieldMapper.fieldType(); + final SortedSetDVOrdinalsIndexFieldData fieldData = context.getForField(fieldType); + return new LateParsingQuery(parentFilter, innerQuery, minChildren(), maxChildren(), + fieldType.name(), scoreMode, fieldData, context.getSearchSimilarity()); + } else { + if (ignoreUnmapped) { + return new MatchNoDocsQuery(); + } else { + throw new QueryShardException(context, "[" + NAME + "] join field has no parent type configured"); + } + } + } + + private Query parentFieldDoToQuery(QueryShardContext context) throws IOException { Query innerQuery; final String[] previousTypes = context.getTypes(); context.setTypes(type); @@ -313,8 +343,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil } finally { context.setTypes(previousTypes); } - - DocumentMapper childDocMapper = context.documentMapper(type); + DocumentMapper childDocMapper = context.getMapperService().documentMapper(type); if (childDocMapper == null) { if (ignoreUnmapped) { return new MatchNoDocsQuery(); @@ -330,16 +359,17 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil DocumentMapper parentDocMapper = context.getMapperService().documentMapper(parentType); if (parentDocMapper == null) { throw new QueryShardException(context, - "[" + NAME + "] Type [" + type + "] points to a non existent parent type [" + parentType + "]"); + "[" + NAME + "] Type [" + type + "] points to a non existent parent type [" + parentType + "]"); } // wrap the query with type query innerQuery = Queries.filtered(innerQuery, childDocMapper.typeFilter(context)); + String joinField = ParentFieldMapper.joinField(parentType); final MappedFieldType parentFieldType = parentDocMapper.parentFieldMapper().getParentJoinFieldType(); final SortedSetDVOrdinalsIndexFieldData fieldData = context.getForField(parentFieldType); return new LateParsingQuery(parentDocMapper.typeFilter(context), innerQuery, minChildren(), maxChildren(), - parentType, scoreMode, fieldData, context.getSearchSimilarity()); + joinField, scoreMode, fieldData, context.getSearchSimilarity()); } /** @@ -358,19 +388,19 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil private final Query innerQuery; private final int minChildren; private final int maxChildren; - private final String parentType; + private final String joinField; private final ScoreMode scoreMode; private final SortedSetDVOrdinalsIndexFieldData fieldDataJoin; private final Similarity similarity; LateParsingQuery(Query toQuery, Query innerQuery, int minChildren, int maxChildren, - String parentType, ScoreMode scoreMode, + String joinField, ScoreMode scoreMode, SortedSetDVOrdinalsIndexFieldData fieldData, Similarity similarity) { this.toQuery = toQuery; this.innerQuery = innerQuery; this.minChildren = minChildren; this.maxChildren = maxChildren; - this.parentType = parentType; + this.joinField = joinField; this.scoreMode = scoreMode; this.fieldDataJoin = fieldData; this.similarity = similarity; @@ -383,7 +413,6 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil return rewritten; } if (reader instanceof DirectoryReader) { - String joinField = ParentFieldMapper.joinField(parentType); IndexSearcher indexSearcher = new IndexSearcher(reader); indexSearcher.setQueryCache(null); indexSearcher.setSimilarity(similarity); @@ -414,18 +443,18 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil if (maxChildren != that.maxChildren) return false; if (!toQuery.equals(that.toQuery)) return false; if (!innerQuery.equals(that.innerQuery)) return false; - if (!parentType.equals(that.parentType)) return false; + if (!joinField.equals(that.joinField)) return false; return scoreMode == that.scoreMode; } @Override public int hashCode() { - return Objects.hash(classHash(), toQuery, innerQuery, minChildren, maxChildren, parentType, scoreMode); + return Objects.hash(getClass(), toQuery, innerQuery, minChildren, maxChildren, joinField, scoreMode); } @Override public String toString(String s) { - return "LateParsingQuery {parentType=" + parentType + "}"; + return "LateParsingQuery {joinField=" + joinField + "}"; } public int getMinChildren() { diff --git a/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java index 7bcbf7c611..3d23fac01b 100644 --- a/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java +++ b/modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java @@ -55,6 +55,8 @@ import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryRewriteContext; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardException; +import org.elasticsearch.join.mapper.ParentIdFieldMapper; +import org.elasticsearch.join.mapper.ParentJoinFieldMapper; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHitField; import org.elasticsearch.search.fetch.subphase.InnerHitsContext; @@ -187,6 +189,35 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu @Override protected Query doToQuery(QueryShardContext context) throws IOException { + if (context.getIndexSettings().isSingleType()) { + return joinFieldDoToQuery(context); + } else { + return parentFieldDoToQuery(context); + } + } + + private Query joinFieldDoToQuery(QueryShardContext context) throws IOException { + ParentJoinFieldMapper joinFieldMapper = ParentJoinFieldMapper.getMapper(context.getMapperService()); + ParentIdFieldMapper parentIdFieldMapper = joinFieldMapper.getParentIdFieldMapper(type, true); + if (parentIdFieldMapper != null) { + Query parentFilter = parentIdFieldMapper.getParentFilter(); + Query innerQuery = Queries.filtered(query.toQuery(context), parentFilter); + Query childFilter = parentIdFieldMapper.getChildrenFilter(); + MappedFieldType fieldType = parentIdFieldMapper.fieldType(); + final SortedSetDVOrdinalsIndexFieldData fieldData = context.getForField(fieldType); + return new HasChildQueryBuilder.LateParsingQuery(childFilter, innerQuery, + HasChildQueryBuilder.DEFAULT_MIN_CHILDREN, HasChildQueryBuilder.DEFAULT_MAX_CHILDREN, + fieldType.name(), score ? ScoreMode.Max : ScoreMode.None, fieldData, context.getSearchSimilarity()); + } else { + if (ignoreUnmapped) { + return new MatchNoDocsQuery(); + } else { + throw new QueryShardException(context, "[" + NAME + "] join field has no parent type configured"); + } + } + } + + private Query parentFieldDoToQuery(QueryShardContext context) throws IOException { Query innerQuery; String[] previousTypes = context.getTypes(); context.setTypes(type); @@ -239,7 +270,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu innerQuery, HasChildQueryBuilder.DEFAULT_MIN_CHILDREN, HasChildQueryBuilder.DEFAULT_MAX_CHILDREN, - type, + ParentFieldMapper.joinField(type), score ? ScoreMode.Max : ScoreMode.None, fieldData, context.getSearchSimilarity()); |