Github user dsmiley commented on a diff in the pull request:

    https://github.com/apache/lucene-solr/pull/416#discussion_r209069776
  
    --- Diff: 
solr/core/src/java/org/apache/solr/response/transform/ChildDocTransformerFactory.java
 ---
    @@ -70,109 +73,59 @@ public DocTransformer create(String field, SolrParams 
params, SolrQueryRequest r
         }
     
         String parentFilter = params.get( "parentFilter" );
    -    if( parentFilter == null ) {
    -      throw new SolrException( ErrorCode.BAD_REQUEST, "Parent filter 
should be sent as parentFilter=filterCondition" );
    -    }
    -
    -    String childFilter = params.get( "childFilter" );
    -    int limit = params.getInt( "limit", 10 );
    -
         BitSetProducer parentsFilter = null;
    -    try {
    -      Query parentFilterQuery = QParser.getParser( parentFilter, 
req).getQuery();
    -      //TODO shouldn't we try to use the Solr filter cache, and then 
ideally implement
    -      //  BitSetProducer over that?
    -      // DocSet parentDocSet = 
req.getSearcher().getDocSet(parentFilterQuery);
    -      // then return BitSetProducer with custom BitSet impl accessing the 
docSet
    -      parentsFilter = new QueryBitSetProducer(parentFilterQuery);
    -    } catch (SyntaxError syntaxError) {
    -      throw new SolrException( ErrorCode.BAD_REQUEST, "Failed to create 
correct parent filter query" );
    -    }
    -
    -    Query childFilterQuery = null;
    -    if(childFilter != null) {
    +    boolean buildHierarchy = params.getBool("hierarchy", false);
    +    if( parentFilter == null) {
    +      if(!buildHierarchy) {
    +        throw new SolrException( ErrorCode.BAD_REQUEST, "Parent filter 
should be sent as parentFilter=filterCondition" );
    +      }
    +      parentsFilter = new QueryBitSetProducer(rootFilter);
    +    } else {
           try {
    -        childFilterQuery = QParser.getParser( childFilter, req).getQuery();
    +        Query parentFilterQuery = QParser.getParser(parentFilter, 
req).getQuery();
    +        //TODO shouldn't we try to use the Solr filter cache, and then 
ideally implement
    +        //  BitSetProducer over that?
    +        // DocSet parentDocSet = 
req.getSearcher().getDocSet(parentFilterQuery);
    +        // then return BitSetProducer with custom BitSet impl accessing 
the docSet
    +        parentsFilter = new QueryBitSetProducer(parentFilterQuery);
           } catch (SyntaxError syntaxError) {
    -        throw new SolrException( ErrorCode.BAD_REQUEST, "Failed to create 
correct child filter query" );
    +        throw new SolrException( ErrorCode.BAD_REQUEST, "Failed to create 
correct parent filter query" );
           }
         }
     
    -    return new ChildDocTransformer( field, parentsFilter, uniqueKeyField, 
req.getSchema(), childFilterQuery, limit);
    -  }
    -}
    -
    -class ChildDocTransformer extends DocTransformer {
    -  private final String name;
    -  private final SchemaField idField;
    -  private final IndexSchema schema;
    -  private BitSetProducer parentsFilter;
    -  private Query childFilterQuery;
    -  private int limit;
    -
    -  public ChildDocTransformer( String name, final BitSetProducer 
parentsFilter, 
    -                              final SchemaField idField, IndexSchema 
schema,
    -                              final Query childFilterQuery, int limit) {
    -    this.name = name;
    -    this.idField = idField;
    -    this.schema = schema;
    -    this.parentsFilter = parentsFilter;
    -    this.childFilterQuery = childFilterQuery;
    -    this.limit = limit;
    -  }
    +    String childFilter = params.get( "childFilter" );
    +    int limit = params.getInt( "limit", 10 );
     
    -  @Override
    -  public String getName()  {
    -    return name;
    -  }
    -  
    -  @Override
    -  public String[] getExtraRequestFields() {
    -    // we always need the idField (of the parent) in order to fill out 
it's children
    -    return new String[] { idField.getName() };
    +    if(buildHierarchy) {
    +      if(childFilter != null) {
    +        childFilter = buildHierarchyChildFilterString(childFilter);
    +        return new ChildDocTransformer(field, parentsFilter, req,
    +            getChildQuery(childFilter, req), limit);
    +      }
    +      return new ChildDocTransformer(field, parentsFilter, req, null, 
limit);
    +    }
    +    return new ChildDocTransformer( field, parentsFilter, req,
    +        childFilter==null? null: getChildQuery(childFilter, req), limit);
       }
     
    -  @Override
    -  public void transform(SolrDocument doc, int docid) {
    -
    -    FieldType idFt = idField.getType();
    -    Object parentIdField = doc.getFirstValue(idField.getName());
    -    
    -    String parentIdExt = parentIdField instanceof IndexableField
    -      ? idFt.toExternal((IndexableField)parentIdField)
    -      : parentIdField.toString();
    -
    +  private static Query getChildQuery(String childFilter, SolrQueryRequest 
req) {
         try {
    -      Query parentQuery = idFt.getFieldQuery(null, idField, parentIdExt);
    -      Query query = new ToChildBlockJoinQuery(parentQuery, parentsFilter);
    -      DocList children = context.getSearcher().getDocList(query, 
childFilterQuery, new Sort(), 0, limit);
    -      if(children.matches() > 0) {
    -        SolrDocumentFetcher docFetcher = 
context.getSearcher().getDocFetcher();
    -
    -        Set<String> dvFieldsToReturn = docFetcher.getNonStoredDVs(true);
    -        boolean shouldDecorateWithDVs = dvFieldsToReturn.size() > 0;
    -        DocIterator i = children.iterator();
    -
    -        while(i.hasNext()) {
    -          Integer childDocNum = i.next();
    -          Document childDoc = context.getSearcher().doc(childDocNum);
    -          // TODO: future enhancement...
    -          // support an fl local param in the transformer, which is used 
to build
    -          // a private ReturnFields instance that we use to prune unwanted 
field 
    -          // names from solrChildDoc
    -          SolrDocument solrChildDoc = 
DocsStreamer.convertLuceneDocToSolrDoc(childDoc, schema,
    -                                                                           
  new SolrReturnFields());
    +      return QParser.getParser( childFilter, req).getQuery();
    +    } catch (SyntaxError syntaxError) {
    +      throw new SolrException( ErrorCode.BAD_REQUEST, "Failed to create 
correct child filter query" );
    +    }
    +  }
     
    -          if (shouldDecorateWithDVs) {
    -            docFetcher.decorateDocValueFields(solrChildDoc, childDocNum, 
dvFieldsToReturn);
    -          }
    -          doc.addChildDocument(solrChildDoc);
    -        }
    -      }
    -      
    -    } catch (IOException e) {
    -      doc.put(name, "Could not fetch child Documents");
    +  protected static String buildHierarchyChildFilterString(String 
queryString) {
    +    List<String> split = StrUtils.splitSmart(queryString, ':');
    --- End diff --
    
    FYI I've rewritten this method to not use splitting & joining in cases like 
this which can use "indexOf"/"lastIndexOf".   I've also increased it's 
robustness to more complicated query examples of multiple conditions.  
    
    For now I think we shouldn't document this; let it be kinda a secret 
feature until we can query (in q/fq) in like-kind.


---

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to