= Searching Nested Child Documents
// 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.

This section exposes potential techniques which can be used for searching deeply nested documents,
show casing how more complex queries can be constructed using some of Solr's query parsers and Doc Transformers.
These features require `\_root_` and `\_nest_path_` to be declared in the schema. +
Please refer to the <<indexing-nested-documents.adoc#indexing-nested-documents, Indexing Nested Documents>>
section for more details about schema and index configuration.


[NOTE]
This section does not show case faceting on nested documents. For nested document faceting, please refer to the
<<blockjoin-faceting#blockjoin-faceting, Block Join Faceting>> section.

== Query Examples

For the upcoming examples, assume the following documents have been indexed:

[source,json]
----
[
  {
    "ID": "1",
    "title": "Cooking Recommendations",
    "tags": ["cooking", "meetup"],
    "posts": [{
        "ID": "2",
        "title": "Cookies",
        "comments": [{
            "ID": "3",
            "content": "Lovely recipe"
          },
          {
            "ID": "4",
            "content": "A-"
          }
        ]
      },
      {
        "ID": "5",
        "title": "Cakes"
      }
    ]
  },
  {
    "ID": "6",
    "title": "For Hire",
    "tags": ["professional", "jobs"],
    "posts": [{
        "ID": "7",
        "title": "Search Engineer",
        "comments": [{
           "ID": "8",
           "content": "I am interested"
         },
         {
           "ID": "9",
           "content": "How large is the team?"
         }
        ]
      },
      {
        "ID": "10",
        "title": "Low level Engineer"
      }
    ]
  }
]
----

=== Child Doc Transformer

Can be used enrich query results with the documents' descendants. +
For a detailed explanation of this transformer, see the section <<transforming-result-documents.adoc#child-childdoctransformerfactory, [child] - ChildDocTransformerFactory>>.

For example, let us examine this query:
`q=ID:1,
fl=ID,[child childFilter=/comments/content:recipe]`. +
The Child Doc Transformer can be used to enrich matching docs with comments that match a particular filter. +
In this particular query, the child Filter will only match the first comment of doc(ID:1),
therefore only that particular comment will be appended to the result.  This is a special syntax feature.

[source,json]
----
 { "response":{"numFound":1,"start":0,"docs":[
       {
           "ID": "1",
           "title": "Cooking Recommendations",
           "tags": ["cooking", "meetup"],
           "posts": [{
               "ID": "2",
               "title": "Cookies",
               "comments": [{
                   "ID": "3",
                   "content": "Lovely recipe"
               }]
             }]
        }]
    }
 }
----

=== Children Query Parser

Can be used to retrieve children of a matching document. +
For a detailed explanation of this parser, see the section <<other-parsers.adoc#block-join-children-query-parser, Block Join Children Query Parser>>.

For example, let us examine this query:
`q={!child of='_nest_path_:/posts}content:"Search Engineer"`. +
The `'of'` filter returns all posts. This is used to filter out all documents in a particular path of the hierarchy(all parents).
The second part of the query is a filter for some parents, which we wish to return their children. +
In this example, all comments of posts which had "Search Engineer in their `content` field will be returned.

[source,json]
----
     { "response":{"numFound":2,"start":0,"docs":[
           {
              "ID": "8",
              "content": "I am interested"
           },
           {
              "ID": "9",
              "content": "How large is the team?"
           }
        ]}
     }
----

=== Parents Query Parser

Can be used to retrieve parents of a child document. +
For a detailed explanation of this parser, see the section <<other-parsers.adoc#block-join-parent-query-parser,Block Join Parent Query Parser>>.

For example, let us examine this query:
`q={!parent which='-_nest_path_:* \*:*'}title:"Search Engineer"`. +
The `'which'` filter returns all root documents.
The second part of this query is a filter to match some child documents.
This query returns the parent at the root(since all parents filter returns root documents) of each
matching child document. In this case, all child documents which had `Search Engineer` in their `title` field.

[source,json]
----
  { "response":{"numFound":1,"start":0,"docs":[{
         "ID": "6",
         "title": "For Hire",
         "tags": ["professional", "jobs"]
         }
    ]}
  }
----

=== Combining Block Join Query Parsers with Child Doc Transformer

The combination of these two features enable seamless creation of powerful queries. +
For example, querying posts which are under a page tagged as a job, contain the words "Search Engineer".
The comments for matching posts can also be fetched, all done in a single Solr Query.

For example, let us examine this query:
`q=+{!child of='-\_nest_path_:* \*:*'}+tags:"jobs" &fl=*,[child]
&fq=\_nest_path_:/posts`. +
This query returns all posts and their comments, which had "Search Engineer" in their title,
and are indexed under a page tagged with "jobs".
The comments are appended to the matching posts, since the ChildDocTransformer is specified under the `fl` parameter.

[source,json]
----
  { "response":{"numFound":1,"start":0,"docs":[
        {
          "ID": "7",
          "title": "Search Engineer",
          "comments": [{
             "ID": "8",
             "content": "I am interested"
           },
           {
             "ID": "9",
             "content": "How large is the team?"
           }
          ]
        },
        {
          "ID": "10",
          "title": "Low level Engineer"
        }]
     }
  }
----
