@Override
  protected Query doToQuery(QueryShardContext context) throws IOException {
    DocumentMapper childDocMapper = context.getMapperService().documentMapper(type);
    if (childDocMapper == null) {
      if (ignoreUnmapped) {
        return new MatchNoDocsQuery();
      } else {
        throw new QueryShardException(
            context, "[" + NAME + "] no mapping found for type [" + type + "]");
      }
    }
    ParentFieldMapper parentFieldMapper = childDocMapper.parentFieldMapper();
    if (parentFieldMapper.active() == false) {
      throw new QueryShardException(
          context, "[" + NAME + "] _parent field has no parent type configured");
    }
    String fieldName = ParentFieldMapper.joinField(parentFieldMapper.type());

    BooleanQuery.Builder query = new BooleanQuery.Builder();
    query.add(new DocValuesTermsQuery(fieldName, id), BooleanClause.Occur.MUST);
    // Need to take child type into account, otherwise a child doc of different type with the same
    // id could match
    query.add(new TermQuery(new Term(TypeFieldMapper.NAME, type)), BooleanClause.Occur.FILTER);
    return query.build();
  }
  @Override
  protected Query doToQuery(QueryShardContext context) throws IOException {
    String field;
    MappedFieldType fieldType = context.fieldMapper(fieldName);
    if (fieldType != null) {
      field = fieldType.names().indexName();
    } else {
      field = fieldName;
    }

    Analyzer analyzerObj;
    if (analyzer == null) {
      if (fieldType != null) {
        analyzerObj = context.getSearchAnalyzer(fieldType);
      } else {
        analyzerObj = context.getMapperService().searchAnalyzer();
      }
    } else {
      analyzerObj = context.getMapperService().analysisService().analyzer(analyzer);
      if (analyzerObj == null) {
        throw new QueryShardException(context, "[common] analyzer [" + analyzer + "] not found");
      }
    }

    Occur highFreqOccur = highFreqOperator.toBooleanClauseOccur();
    Occur lowFreqOccur = lowFreqOperator.toBooleanClauseOccur();

    ExtendedCommonTermsQuery commonsQuery =
        new ExtendedCommonTermsQuery(
            highFreqOccur, lowFreqOccur, cutoffFrequency, disableCoord, fieldType);
    return parseQueryString(
        commonsQuery,
        text,
        field,
        analyzerObj,
        lowFreqMinimumShouldMatch,
        highFreqMinimumShouldMatch);
  }
  @Override
  protected Query doToQuery(QueryShardContext context) throws IOException {
    Query innerQuery;
    String[] previousTypes = context.getTypes();
    context.setTypes(type);
    try {
      innerQuery = query.toQuery(context);
    } finally {
      context.setTypes(previousTypes);
    }

    DocumentMapper parentDocMapper = context.getMapperService().documentMapper(type);
    if (parentDocMapper == null) {
      if (ignoreUnmapped) {
        return new MatchNoDocsQuery();
      } else {
        throw new QueryShardException(
            context,
            "[" + NAME + "] query configured 'parent_type' [" + type + "] is not a valid type");
      }
    }

    Set<String> childTypes = new HashSet<>();
    ParentChildIndexFieldData parentChildIndexFieldData = null;
    for (DocumentMapper documentMapper : context.getMapperService().docMappers(false)) {
      ParentFieldMapper parentFieldMapper = documentMapper.parentFieldMapper();
      if (parentFieldMapper.active() && type.equals(parentFieldMapper.type())) {
        childTypes.add(documentMapper.type());
        parentChildIndexFieldData = context.getForField(parentFieldMapper.fieldType());
      }
    }

    if (childTypes.isEmpty()) {
      throw new QueryShardException(
          context, "[" + NAME + "] no child types found for type [" + type + "]");
    }

    Query childrenQuery;
    if (childTypes.size() == 1) {
      DocumentMapper documentMapper =
          context.getMapperService().documentMapper(childTypes.iterator().next());
      childrenQuery = documentMapper.typeFilter();
    } else {
      BooleanQuery.Builder childrenFilter = new BooleanQuery.Builder();
      for (String childrenTypeStr : childTypes) {
        DocumentMapper documentMapper = context.getMapperService().documentMapper(childrenTypeStr);
        childrenFilter.add(documentMapper.typeFilter(), BooleanClause.Occur.SHOULD);
      }
      childrenQuery = childrenFilter.build();
    }

    // wrap the query with type query
    innerQuery = Queries.filtered(innerQuery, parentDocMapper.typeFilter());
    return new HasChildQueryBuilder.LateParsingQuery(
        childrenQuery,
        innerQuery,
        HasChildQueryBuilder.DEFAULT_MIN_CHILDREN,
        HasChildQueryBuilder.DEFAULT_MAX_CHILDREN,
        type,
        score ? ScoreMode.Max : ScoreMode.None,
        parentChildIndexFieldData,
        context.getSearchSimilarity());
  }