过滤nested文档
6.1前 _type 不是以 "__"开头的。
6.1之后根据是否存在_primary_term属性
org.elasticsearch.index.query.NestedQueryBuilder doToQuery
/**
* Creates a new non-nested docs query
* @param indexVersionCreated the index version created since newer indices can identify a parent field more efficiently
*/
public static Query newNonNestedFilter(Version indexVersionCreated) {
if (indexVersionCreated.onOrAfter(Version.V_6_1_0)) {
return new DocValuesFieldExistsQuery(SeqNoFieldMapper.PRIMARY_TERM_NAME);
} else {
return new BooleanQuery.Builder()
.add(new MatchAllDocsQuery(), Occur.FILTER)
.add(newNestedFilter(), Occur.MUST_NOT)
.build();
}
}
最终会调用Lucene的ToParentBlockJoinQuery来完成查找。
public ESToParentBlockJoinQuery(Query childQuery, BitSetProducer parentsFilter, ScoreMode scoreMode, String path) {
this(new ToParentBlockJoinQuery(childQuery, parentsFilter, scoreMode), path, scoreMode);
}
父子查询
public abstract class JoinQueryBuilders {
/**
* Constructs a new has_child query, with the child type and the query to run on the child documents. The
* results of this query are the parent docs that those child docs matched.
*
* @param type The child type.
* @param query The query.
* @param scoreMode How the scores from the children hits should be aggregated into the parent hit.
*/
public static HasChildQueryBuilder hasChildQuery(String type, QueryBuilder query, ScoreMode scoreMode) {
return new HasChildQueryBuilder(type, query, scoreMode);
}
/**
* Constructs a new parent query, with the parent type and the query to run on the parent documents. The
* results of this query are the children docs that those parent docs matched.
*
* @param type The parent type.
* @param query The query.
* @param score Whether the score from the parent hit should propagate to the child hit
*/
public static HasParentQueryBuilder hasParentQuery(String type, QueryBuilder query, boolean score) {
return new HasParentQueryBuilder(type, query, score);
}
/**
* Constructs a new parent id query that returns all child documents of the specified type that
* point to the specified id.
*/
public static ParentIdQueryBuilder parentId(String type, String id) {
return new ParentIdQueryBuilder(type, id);
}
}
最终调用了JoinUtil.createJoinQuery来完成join操作
@Override
public Query rewrite(IndexReader reader) throws IOException {
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
if (reader instanceof DirectoryReader) {
IndexSearcher indexSearcher = new IndexSearcher(reader);
indexSearcher.setQueryCache(null);
indexSearcher.setSimilarity(similarity);
IndexOrdinalsFieldData indexParentChildFieldData = fieldDataJoin.loadGlobal((DirectoryReader) reader);
OrdinalMap ordinalMap = indexParentChildFieldData.getOrdinalMap();
// 调用JoinUtil完成join操作
return JoinUtil.createJoinQuery(joinField, innerQuery, toQuery, indexSearcher, scoreMode,
ordinalMap, minChildren, maxChildren);
} else {
if (reader.leaves().isEmpty() && reader.numDocs() == 0) {
// asserting reader passes down a MultiReader during rewrite which makes this
// blow up since for this query to work we have to have a DirectoryReader otherwise
// we can't load global ordinals - for this to work we simply check if the reader has no leaves
// and rewrite to match nothing
return new MatchNoDocsQuery();
}
throw new IllegalStateException("can't load global ordinals for reader of type: " +
reader.getClass() + " must be a DirectoryReader");
}
}