You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2020/09/01 22:41:38 UTC

[lucene-solr] branch jira/SOLR-14383 updated: fill in alternate XML/SolrJ examples for existing JSON examples

This is an automated email from the ASF dual-hosted git repository.

hossman pushed a commit to branch jira/SOLR-14383
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/jira/SOLR-14383 by this push:
     new 5d29327  fill in alternate XML/SolrJ examples for existing JSON examples
5d29327 is described below

commit 5d293276a343bb4905198660191b867b768dea29
Author: Chris Hostetter <ho...@apache.org>
AuthorDate: Tue Sep 1 15:40:40 2020 -0700

    fill in alternate XML/SolrJ examples for existing JSON examples
---
 .../src/indexing-nested-documents.adoc             | 149 +++++++++--
 .../IndexingNestedDocuments.java                   | 280 +++++++++++++++++++++
 2 files changed, 411 insertions(+), 18 deletions(-)

diff --git a/solr/solr-ref-guide/src/indexing-nested-documents.adoc b/solr/solr-ref-guide/src/indexing-nested-documents.adoc
index 4a22518..c8665dd 100644
--- a/solr/solr-ref-guide/src/indexing-nested-documents.adoc
+++ b/solr/solr-ref-guide/src/indexing-nested-documents.adoc
@@ -1,4 +1,6 @@
 = Indexing Nested Child Documents
+:solr-root-path: ../../
+:example-source-dir: {solr-root-path}solrj/src/test/org/apache/solr/client/ref_guide_examples/
 // 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
@@ -118,18 +120,89 @@ The <<uploading-data-with-index-handlers#json-update-convenience-paths,`/update/
 [.tab-label]*XML*
 [source,xml]
 ----
-nocommit: TODO: XML equivilent of JSON above
+<add>
+  <doc>
+    <field name="id">P11!prod</field>
+    <field name="name_s">Swingline Stapler</field>
+    <field name="description_t">The Cadillac of office staplers ...</field>
+    <field name="skus">
+      <doc>
+        <field name="id">P11!S21</field>
+        <field name="color_s">RED</field>
+        <field name="price_i">42</field>
+        <field name="manuals">
+          <doc>
+            <field name="id">P11!D41</field>
+            <field name="name_s">Red Swingline Brochure</field>
+            <field name="pages_i">1</field>
+            <field name="content_t">...</field>
+          </doc>
+        </field>
+      </doc>
+      <doc>
+        <field name="id">P11!S31</field>
+        <field name="color_s">BLACK</field>
+        <field name="price_i">3</field>
+      </doc>
+    </field>
+    <field name="manuals">
+      <doc>
+        <field name="id">P11!D51</field>
+        <field name="name_s">Quick Reference Guide</field>
+        <field name="pages_i">1</field>
+        <field name="content_t">How to use your stapler ...</field>
+      </doc>
+      <doc>
+        <field name="id">P11!D61</field>
+        <field name="name_s">Warranty Details</field>
+        <field name="pages_i">42</field>
+        <field name="content_t">... lifetime guarantee ...</field>
+      </doc>
+    </field>
+  </doc>
+  <doc>
+    <field name="id">P22!prod</field>
+    <field name="name_s">Mont Blanc Fountain Pen</field>
+    <field name="description_t">A Premium Writing Instrument ...</field>
+    <field name="skus">
+      <doc>
+        <field name="id">P22!S22</field>
+        <field name="color_s">RED</field>
+        <field name="price_i">89</field>
+        <field name="manuals">
+          <doc>
+            <field name="id">P22!D42</field>
+            <field name="name_s">Red Mont Blanc Brochure</field>
+            <field name="pages_i">1</field>
+            <field name="content_t">...</field>
+          </doc>
+        </field>
+      </doc>
+      <doc>
+        <field name="id">P22!S32</field>
+        <field name="color_s">BLACK</field>
+        <field name="price_i">67</field>
+      </doc>
+    </field>
+    <field name="manuals">
+      <doc>
+        <field name="id">P22!D52</field>
+        <field name="name_s">How To Use A Pen</field>
+        <field name="pages_i">42</field>
+        <field name="content_t">Start by removing the cap ...</field>
+      </doc>
+    </field>
+  </doc>
+</add>
 ----
 ====
 
 [example.tab-pane#solrj]
 ====
 [.tab-label]*SolrJ*
-[source,java]
+[source,java,indent=0]
 ----
-nocommit: TODO: SolrJ equivilent of JSON above
-nocommit: ... do we even have a test proving this works correctly
-nocommit: the SolrInputDocument methods for addChildDocument methods still don't take "field name"
+include::{example-source-dir}IndexingNestedDocuments.java[tag=nest-path]
 ----
 ====
 --
@@ -168,7 +241,7 @@ There are several additional schema considerations that should be considered for
 ** If you do not use `\_nest_path_` it is strongly recomended that every document have some field that differentiates root documents from their nested children -- and differentiates different "types" of child documents.  This is not strictly neccessary, so long as it's possible to write a "filter" query that can be used to isolate and select only parent documents for use in the <<other-parsers.adoc#block-join-query-parsers,block join query parsers>> and <<searching-nested-documents.adoc# [...]
 * `\_nest_parent_` is an optional field that (if defined) will be populated by Solr automatically to store the `id` of each document's _immediate_ parent document (if there is one).
 +
-[sourece,xml]
+[source,xml]
 ----
 <field name="_nest_parent_" type="string" indexed="true" stored="true" />
 ----
@@ -214,7 +287,7 @@ Although not recommended, it is also possible to index child documents "anonymou
          "price_i": 42,
          "_childDocuments_": [
              { "id": "P11!D41",
-               "type_s": "DOC",
+               "type_s": "MANUAL",
                "name_s": "Red Swingline Brochure",
                "pages_i":1,
                "content_t": "..."
@@ -226,13 +299,13 @@ Although not recommended, it is also possible to index child documents "anonymou
          "price_i": 3
        },
        { "id": "P11!D51",
-         "type_s": "DOC",
+         "type_s": "MANUAL",
          "name_s": "Quick Reference Guide",
          "pages_i":1,
          "content_t": "How to use your stapler ..."
        },
        { "id": "P11!D61",
-         "type_s": "DOC",
+         "type_s": "MANUAL",
          "name_s": "Warranty Details",
          "pages_i":42,
          "content_t": "... lifetime guarantee ..."
@@ -247,16 +320,56 @@ Although not recommended, it is also possible to index child documents "anonymou
 [.tab-label]*XML*
 [source,xml]
 ----
-nocommit: TODO: XML equivilent of JSON above
+<add>
+  <doc>
+    <field name="id">P11!prod</field>
+    <field name="type_s">PRODUCT</field>
+    <field name="name_s">Swingline Stapler</field>
+    <field name="description_t">The Cadillac of office staplers ...</field>
+    <doc>
+      <field name="id">P11!S21</field>
+      <field name="type_s">SKU</field>
+      <field name="color_s">RED</field>
+      <field name="price_i">42</field>
+      <doc>
+        <field name="id">P11!D41</field>
+        <field name="type_s">MANUAL</field>
+        <field name="name_s">Red Swingline Brochure</field>
+        <field name="pages_i">1</field>
+        <field name="content_t">...</field>
+      </doc>
+    </doc>
+    <doc>
+      <field name="id">P11!S31</field>
+      <field name="type_s">SKU</field>
+      <field name="color_s">BLACK</field>
+      <field name="price_i">3</field>
+    </doc>
+    <doc>
+      <field name="id">P11!D51</field>
+      <field name="type_s">MANUAL</field>
+      <field name="name_s">Quick Reference Guide</field>
+      <field name="pages_i">1</field>
+      <field name="content_t">How to use your stapler ...</field>
+    </doc>
+    <doc>
+      <field name="id">P11!D61</field>
+      <field name="type_s">MANUAL</field>
+      <field name="name_s">Warranty Details</field>
+      <field name="pages_i">42</field>
+      <field name="content_t">... lifetime guarantee ...</field>
+    </doc>
+  </doc>
+</add>
 ----
 ====
 
 [example.tab-pane#anon_solrj]
 ====
 [.tab-label]*SolrJ*
-[source,java]
+[source,java,indent=0]
 ----
-nocommit: TODO: SolrJ equivilent of JSON above
+include::{example-source-dir}IndexingNestedDocuments.java[tag=anon-kids]
 ----
 ====
 
@@ -290,7 +403,7 @@ $ curl --globoff 'http://localhost:8983/solr/gettingstarted/select?omitHeader=tr
         "_childDocuments_":[
         {
           "id":"P11!D41",
-          "type_s":"DOC",
+          "type_s":"MANUAL",
           "name_s":"Red Swingline Brochure",
           "pages_i":1,
           "content_t":"...",
@@ -309,14 +422,14 @@ $ curl --globoff 'http://localhost:8983/solr/gettingstarted/select?omitHeader=tr
           "_version_":1673055562829398016},
         {
           "id":"P11!D51",
-          "type_s":"DOC",
+          "type_s":"MANUAL",
           "name_s":"Quick Reference Guide",
           "pages_i":1,
           "content_t":"How to use your stapler ...",
           "_version_":1673055562829398016},
         {
           "id":"P11!D61",
-          "type_s":"DOC",
+          "type_s":"MANUAL",
           "name_s":"Warranty Details",
           "pages_i":42,
           "content_t":"... lifetime guarantee ...",
@@ -343,7 +456,7 @@ $ curl --globoff 'http://localhost:8983/solr/gettingstarted/select?omitHeader=tr
     <long name="_version_">1673055562829398016</long>
     <doc>
       <str name="id">P11!D41</str>
-      <str name="type_s">DOC</str>
+      <str name="type_s">MANUAL</str>
       <str name="name_s">Red Swingline Brochure</str>
       <int name="pages_i">1</int>
       <str name="content_t">...</str>
@@ -362,14 +475,14 @@ $ curl --globoff 'http://localhost:8983/solr/gettingstarted/select?omitHeader=tr
       <long name="_version_">1673055562829398016</long></doc>
     <doc>
       <str name="id">P11!D51</str>
-      <str name="type_s">DOC</str>
+      <str name="type_s">MANUAL</str>
       <str name="name_s">Quick Reference Guide</str>
       <int name="pages_i">1</int>
       <str name="content_t">How to use your stapler ...</str>
       <long name="_version_">1673055562829398016</long></doc>
     <doc>
       <str name="id">P11!D61</str>
-      <str name="type_s">DOC</str>
+      <str name="type_s">MANUAL</str>
       <str name="name_s">Warranty Details</str>
       <int name="pages_i">42</int>
       <str name="content_t">... lifetime guarantee ...</str>
diff --git a/solr/solrj/src/test/org/apache/solr/client/ref_guide_examples/IndexingNestedDocuments.java b/solr/solrj/src/test/org/apache/solr/client/ref_guide_examples/IndexingNestedDocuments.java
new file mode 100644
index 0000000..9d22119
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/ref_guide_examples/IndexingNestedDocuments.java
@@ -0,0 +1,280 @@
+/*
+ * 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.client.ref_guide_examples;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+
+import org.apache.solr.cloud.SolrCloudTestCase;
+
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.util.ExternalPaths;
+
+import org.junit.After;
+import org.junit.BeforeClass;
+
+/**
+ * Example SolrJ usage for indexing nested documents
+ *
+ * Snippets surrounded by "tag" and "end" comments are extracted and used in the Solr Reference Guide.
+ */
+public class IndexingNestedDocuments extends SolrCloudTestCase {
+  public static final String ANON_KIDS_CONFIG = "anon_kids_configset";
+  @BeforeClass
+  public static void setupCluster() throws Exception {
+    configureCluster(1)
+      // when indexing 'anonymous' kids, we need a schema that doesn't use _nest_path_ so
+      // that we can use [child] transformer with a parentFilter...
+      .addConfig(ANON_KIDS_CONFIG, new File(ExternalPaths.TECHPRODUCTS_CONFIGSET).toPath())
+      .configure();
+  }
+
+  @After
+  public void cleanCollections() throws Exception {
+    cluster.deleteAllCollections();
+  }
+
+  /**
+   * Syntactic sugar so code snippet doesn't refer to test-framework specific method name 
+   */
+  public static SolrClient getSolrClient() {
+    return cluster.getSolrClient();
+  }
+
+  /**
+   * Demo of using anonymous children when indexing hierarchical documents.
+   * This test code is used as an 'include' from the ref-guide
+   */
+  public void testIndexingAnonKids() throws Exception {
+    final String collection = "test_anon";
+    CollectionAdminRequest.createCollection(collection, ANON_KIDS_CONFIG, 1, 1).process(cluster.getSolrClient());
+    cluster.getSolrClient().setDefaultCollection(collection);
+    
+    //
+    // DO NOT MODIFY THESE EXAMPLE DOCS WITH OUT MAKING THE SAME CHANGES TO THE JSON AND XML
+    // EQUIVILENT EXAMPLES IN 'indexing-nested-documents.adoc'
+    //
+
+    // tag::anon-kids[]
+    final SolrClient client = getSolrClient();
+
+    final SolrInputDocument p1 = new SolrInputDocument();
+    p1.setField("id", "P11!prod");
+    p1.setField("type_s", "PRODUCT");
+    p1.setField("name_s", "Swingline Stapler");
+    p1.setField("description_t", "The Cadillac of office staplers ...");
+    {
+      final SolrInputDocument s1 = new SolrInputDocument();
+      s1.setField("id", "P11!S21");
+      s1.setField("type_s", "SKU");
+      s1.setField("color_s", "RED");
+      s1.setField("price_i", 42);
+      { 
+        final SolrInputDocument m1 = new SolrInputDocument();
+        m1.setField("id", "P11!D41");
+        m1.setField("type_s", "MANUAL");
+        m1.setField("name_s", "Red Swingline Brochure");
+        m1.setField("pages_i", 1);
+        m1.setField("content_t", "...");
+
+        s1.addChildDocument(m1);
+      }
+
+      final SolrInputDocument s2 = new SolrInputDocument();
+      s2.setField("id", "P11!S31");
+      s2.setField("type_s", "SKU");
+      s2.setField("color_s", "BLACK");
+      s2.setField("price_i", 3);
+
+      final SolrInputDocument m1 = new SolrInputDocument();
+      m1.setField("id", "P11!D51");
+      m1.setField("type_s", "MANUAL");
+      m1.setField("name_s", "Quick Reference Guide");
+      m1.setField("pages_i", 1);
+      m1.setField("content_t", "How to use your stapler ...");
+
+      final SolrInputDocument m2 = new SolrInputDocument();
+      m2.setField("id", "P11!D61");
+      m2.setField("type_s", "MANUAL");
+      m2.setField("name_s", "Warranty Details");
+      m2.setField("pages_i", 42);
+      m2.setField("content_t", "... lifetime guarantee ...");
+
+      p1.addChildDocuments(Arrays.asList(s1, s2, m1, m2));
+    }
+    
+    client.add(p1);
+    // end::anon-kids[]
+    
+    client.commit();
+
+    final SolrDocumentList docs = getSolrClient().query
+      (new SolrQuery("description_t:Cadillac").set("fl", "*,[child parentFilter='type_s:PRODUCT']")).getResults();
+    
+    assertEquals(1, docs.getNumFound());
+    assertEquals("P11!prod", docs.get(0).getFieldValue("id"));
+
+    // [child] returns a flat list of all (anon) descendents
+    assertEquals(5, docs.get(0).getChildDocumentCount());
+    assertEquals(5, docs.get(0).getChildDocuments().size());
+
+    // flat list is depth first...
+    final SolrDocument red_stapler_brochure = docs.get(0).getChildDocuments().get(0);
+    assertEquals("P11!D41", red_stapler_brochure.getFieldValue("id"));
+    
+    final SolrDocument red_stapler = docs.get(0).getChildDocuments().get(1);
+    assertEquals("P11!S21", red_stapler.getFieldValue("id"));
+
+  }
+  
+  /**
+   * Demo of using <code>NestPath</code> related psuedo-fields when indexing hierarchical documents.
+   * This test code is used as an 'include' from the ref-guide
+   */
+  public void testIndexingUsingNestPath() throws Exception {
+    final String collection = "test_anon";
+    CollectionAdminRequest.createCollection(collection, 1, 1).process(cluster.getSolrClient());
+    cluster.getSolrClient().setDefaultCollection(collection);
+    
+    //
+    // DO NOT MODIFY THESE EXAMPLE DOCS WITH OUT MAKING THE SAME CHANGES TO THE JSON AND XML
+    // EQUIVILENT EXAMPLES IN 'indexing-nested-documents.adoc'
+    //
+
+    // tag::nest-path[]
+    final SolrClient client = getSolrClient();
+
+    final SolrInputDocument p1 = new SolrInputDocument();
+    p1.setField("id", "P11!prod");
+    p1.setField("name_s", "Swingline Stapler");
+    p1.setField("description_t", "The Cadillac of office staplers ...");
+    {
+      final SolrInputDocument s1 = new SolrInputDocument();
+      s1.setField("id", "P11!S21");
+      s1.setField("color_s", "RED");
+      s1.setField("price_i", 42);
+      { 
+        final SolrInputDocument m1 = new SolrInputDocument();
+        m1.setField("id", "P11!D41");
+        m1.setField("name_s", "Red Swingline Brochure");
+        m1.setField("pages_i", 1);
+        m1.setField("content_t", "...");
+
+        s1.setField("manuals", m1);
+      }
+
+      final SolrInputDocument s2 = new SolrInputDocument();
+      s2.setField("id", "P11!S31");
+      s2.setField("color_s", "BLACK");
+      s2.setField("price_i", 3);
+      
+      p1.setField("skus", Arrays.asList(s1, s2));
+    }
+    {
+      final SolrInputDocument m1 = new SolrInputDocument();
+      m1.setField("id", "P11!D51");
+      m1.setField("name_s", "Quick Reference Guide");
+      m1.setField("pages_i", 1);
+      m1.setField("content_t", "How to use your stapler ...");
+
+      final SolrInputDocument m2 = new SolrInputDocument();
+      m2.setField("id", "P11!D61");
+      m2.setField("name_s", "Warranty Details");
+      m2.setField("pages_i", 42);
+      m2.setField("content_t", "... lifetime guarantee ...");
+
+      p1.setField("manuals", Arrays.asList(m1, m2));
+    }
+
+    final SolrInputDocument p2 = new SolrInputDocument();
+    p2.setField("id", "P22!prod");
+    p2.setField("name_s", "Mont Blanc Fountain Pen");
+    p2.setField("description_t", "A Premium Writing Instrument ...");
+    {
+      final SolrInputDocument s1 = new SolrInputDocument();
+      s1.setField("id", "P22!S22");
+      s1.setField("color_s", "RED");
+      s1.setField("price_i", 89);
+      { 
+        final SolrInputDocument m1 = new SolrInputDocument();
+        m1.setField("id", "P22!D42");
+        m1.setField("name_s", "Red Mont Blanc Brochure");
+        m1.setField("pages_i", 1);
+        m1.setField("content_t", "...");
+
+        s1.setField("manuals", m1);
+      }
+      
+      final SolrInputDocument s2 = new SolrInputDocument();
+      s2.setField("id", "P22!S32");
+      s2.setField("color_s", "BLACK");
+      s2.setField("price_i", 67);
+      
+      p2.setField("skus", Arrays.asList(s1, s2));
+    }
+    {
+      final SolrInputDocument m1 = new SolrInputDocument();
+      m1.setField("id", "P22!D52");
+      m1.setField("name_s", "How To Use A Pen");
+      m1.setField("pages_i", 42);
+      m1.setField("content_t", "Start by removing the cap ...");
+
+      p2.setField("manuals", m1);
+    }
+    
+    client.add(Arrays.asList(p1, p2));
+    // end::nest-path[]
+    
+    client.commit();
+
+
+    // Now a quick sanity check that the nest path is working properly...
+
+    final SolrDocumentList docs = getSolrClient().query
+      (new SolrQuery("description_t:Writing").set("fl", "*,[child]")).getResults();
+    
+    assertEquals(1, docs.getNumFound());
+    assertEquals("P22!prod", docs.get(0).getFieldValue("id"));
+    
+    assertEquals(1, docs.get(0).getFieldValues("manuals").size());
+    assertEquals(SolrDocument.class, docs.get(0).getFieldValues("manuals").iterator().next().getClass());
+
+    assertEquals(2, docs.get(0).getFieldValues("skus").size());
+    final List<Object> skus = new ArrayList<>(docs.get(0).getFieldValues("skus"));
+    
+    assertEquals(SolrDocument.class, skus.get(0).getClass());
+    assertEquals(SolrDocument.class, skus.get(1).getClass());
+    
+    final SolrDocument red_pen = (SolrDocument) skus.get(0);
+    assertEquals("P22!S22", red_pen.getFieldValue("id"));
+
+    assertEquals(1, red_pen.getFieldValues("manuals").size());
+    assertEquals(SolrDocument.class, red_pen.getFieldValues("manuals").iterator().next().getClass());
+
+    final SolrDocument red_pen_brochure = (SolrDocument) red_pen.getFieldValues("manuals").iterator().next();
+    assertEquals("P22!D42", red_pen_brochure.getFieldValue("id"));
+  }
+}