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"));
+ }
+}