Github user dsmiley commented on a diff in the pull request:
https://github.com/apache/lucene-solr/pull/416#discussion_r205488727
--- Diff:
solr/core/src/test/org/apache/solr/response/transform/TestDeeplyNestedChildDocTransformer.java
---
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.response.transform;
+
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.google.common.collect.Iterables;
+import org.apache.lucene.document.StoredField;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.BasicResultContext;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestDeeplyNestedChildDocTransformer extends SolrTestCaseJ4 {
+
+ private static AtomicInteger counter = new AtomicInteger();
+ private static final char PATH_SEP_CHAR = '/';
+ private static final String[] types = {"donut", "cake"};
+ private static final String[] ingredients = {"flour", "cocoa",
"vanilla"};
+ private static final Iterator<String> ingredientsCycler =
Iterables.cycle(ingredients).iterator();
+ private static final String[] names = {"Yaz", "Jazz", "Costa"};
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ initCore("solrconfig-update-processor-chains.xml", "schema15.xml");
+ }
+
+ @After
+ public void after() throws Exception {
+ assertU(delQ("*:*"));
+ assertU(commit());
+ counter.set(0); // reset id counter
+ }
+
+ @Test
+ public void testParentFilterJSON() throws Exception {
+ indexSampleData(10);
+ String[] tests = new String[] {
+ "/response/docs/[0]/type_s==[donut]",
+ "/response/docs/[0]/toppings/[0]/type_s==[Regular]",
+ "/response/docs/[0]/toppings/[1]/type_s==[Chocolate]",
+ "/response/docs/[0]/toppings/[0]/ingredients/[0]/name_s==[cocoa]",
+ "/response/docs/[0]/toppings/[1]/ingredients/[1]/name_s==[cocoa]",
+ "/response/docs/[0]/lonely/test_s==[testing]",
+ "/response/docs/[0]/lonely/lonelyGrandChild/test2_s==[secondTest]",
+ };
+
+ try(SolrQueryRequest req = req("q", "type_s:donut", "sort", "id asc",
"fl", "*, _nest_path_, [child hierarchy=true]")) {
+ BasicResultContext res = (BasicResultContext)
h.queryAndResponse("/select", req).getResponse();
+ Iterator<SolrDocument> docsStreamer = res.getProcessedDocuments();
+ while (docsStreamer.hasNext()) {
+ SolrDocument doc = docsStreamer.next();
+ int currDocId = Integer.parseInt(((StoredField)
doc.getFirstValue("id")).stringValue());
+ assertEquals("queried docs are not equal to expected output for
id: " + currDocId, fullNestedDocTemplate(currDocId), doc.toString());
+ }
+ }
+
+ assertJQ(req("q", "type_s:donut",
+ "sort", "id asc",
+ "fl", "*, _nest_path_, [child hierarchy=true]"),
+ tests);
+ }
+
+ @Test
+ public void testExactPath() throws Exception {
+ indexSampleData(2);
+ String[] tests = {
+ "/response/numFound==4",
+ "/response/docs/[0]/_nest_path_=='toppings#0'",
+ "/response/docs/[1]/_nest_path_=='toppings#0'",
+ "/response/docs/[2]/_nest_path_=='toppings#1'",
+ "/response/docs/[3]/_nest_path_=='toppings#1'",
+ };
+
+ assertJQ(req("q", "_nest_path_:*toppings/",
+ "sort", "_nest_path_ asc",
+ "fl", "*, _nest_path_"),
+ tests);
+
+ assertJQ(req("q", "+_nest_path_:\"toppings/\"",
+ "sort", "_nest_path_ asc",
+ "fl", "*, _nest_path_"),
+ tests);
+ }
+
+ @Test
+ public void testChildFilterJSON() throws Exception {
+ indexSampleData(10);
+ String[] tests = new String[] {
+ "/response/docs/[0]/type_s==[donut]",
+ "/response/docs/[0]/toppings/[0]/type_s==[Regular]",
+ };
+
+ assertJQ(req("q", "type_s:donut",
+ "sort", "id asc",
+ "fl", "*,[child hierarchy=true
childFilter='toppings/type_s:Regular']"),
+ tests);
+ }
+
+ @Test
+ public void testGrandChildFilterJSON() throws Exception {
+ indexSampleData(10);
+ String[] tests = new String[] {
+ "/response/docs/[0]/type_s==[donut]",
+ "/response/docs/[0]/toppings/[0]/ingredients/[0]/name_s==[cocoa]"
+ };
+
+ try(SolrQueryRequest req = req("q", "type_s:donut", "sort", "id asc",
+ "fl", "*,[child hierarchy=true childFilter='toppings" +
PATH_SEP_CHAR + "ingredients" + PATH_SEP_CHAR + "name_s:cocoa']")) {
+ BasicResultContext res = (BasicResultContext)
h.queryAndResponse("/select", req).getResponse();
+ Iterator<SolrDocument> docsStreamer = res.getProcessedDocuments();
+ while (docsStreamer.hasNext()) {
+ SolrDocument doc = docsStreamer.next();
+ int currDocId = Integer.parseInt(((StoredField)
doc.getFirstValue("id")).stringValue());
+ assertEquals("queried docs are not equal to expected output for
id: " + currDocId, grandChildDocTemplate(currDocId), doc.toString());
+ }
+ }
+
+
+
+ assertJQ(req("q", "type_s:donut",
+ "sort", "id asc",
+ "fl", "*,[child hierarchy=true childFilter='toppings" +
PATH_SEP_CHAR + "ingredients" + PATH_SEP_CHAR + "name_s:cocoa']"),
+ tests);
+ }
+
+ @Test
+ public void testSingularChildFilterJSON() throws Exception {
+ indexSampleData(10);
+ String[] tests = new String[] {
+ "/response/docs/[0]/type_s==[cake]",
+ "/response/docs/[0]/lonely/test_s==[testing]",
+ "/response/docs/[0]/lonely/lonelyGrandChild/test2_s==[secondTest]"
+ };
+
+ assertJQ(req("q", "type_s:cake",
+ "sort", "id asc",
+ "fl", "*,[child hierarchy=true childFilter='lonely" +
PATH_SEP_CHAR + "lonelyGrandChild" + PATH_SEP_CHAR + "test2_s:secondTest']"),
+ tests);
+ }
+
+ private void indexSampleData(int numDocs) throws Exception {
+ for(int i = 0; i < numDocs; ++i) {
+ updateJ(generateDocHierarchy(i), params("update.chain", "nested"));
+ }
+ assertU(commit());
+ }
+
+ private static String id() {
+ return "" + counter.incrementAndGet();
+ }
+
+ private static String grandChildDocTemplate(int id) {
+ int docNum = id / 8; // the index of docs sent to solr in the
AddUpdateCommand. e.g. first doc is 0
+ return
"SolrDocument{id=stored,indexed,tokenized,omitNorms,indexOptions=DOCS<id:" + id
+ ">, type_s=[stored,indexed,tokenized,omitNorms,indexOptions=DOCS<type_s:" +
types[docNum % types.length] + ">],
name_s=[stored,indexed,tokenized,omitNorms,indexOptions=DOCS<name_s:" +
names[docNum % names.length] + ">], " +
--- End diff --
Hmmmm; this isn't *quite* what I had in mind. The
"stored,indexed,tokenized,..." stuff is not what I expected. Apparently, a
document.toString may not be a good a choice. Can you JSONify this? Either
query Solr for a JSON response and use that (this approach is semi-common in
Solr tests, e.g. TestJsonFacets line 192 (params to calling testJQ()) , or use
JSONWriter.writeSolrDocument() somehow to avoid a search if you want to go that
route?
It's too bad we have to see both id & root fields in the document; it'd be
nice if the child doc transformer had "fl".
Ultimately, we'd like to see something easy to read -- a JSON structured
nested docs with as little noise as possible.
---
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]