| = JSON Faceting Domain Changes |
| :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 |
| // 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. |
| |
| Facet computation operates on a "domain" of documents. By default, this domain consists of the documents matched by the main query. For sub-facets, the domain consists of all documents placed in their bucket by the parent facet. |
| |
| Users can also override the "domain" of a facet that partitions data, using an explicit `domain` attribute whose value is a JSON object that can support various options for restricting, expanding, or completely changing the original domain before the buckets are computed for the associated facet. |
| |
| [NOTE] |
| ==== |
| `domain` changes can only be specified on individual facets that do data partitioning -- not statistical/metric facets, or groups of facets. |
| |
| A `\*:*` query facet with a `domain` change can be used to group multiple sub-facets of any type, for the purpose of applying a common domain change. |
| ==== |
| |
| |
| == Adding Domain Filters |
| |
| The simplest example of a domain change is to specify an additional filter which will be applied to the existing domain. This can be done via the `filter` keyword in the `domain` block of the facet. |
| |
| [.dynamic-tabs] |
| -- |
| [example.tab-pane#curl-json-facet-filtered-domain] |
| ==== |
| [.tab-label]*curl* |
| [source,bash] |
| ---- |
| curl http://localhost:8983/solr/techproducts/query -d ' |
| { |
| "query": "*:*", |
| "facet": { |
| "categories": { |
| "type": "terms", |
| "field": "cat", |
| "limit": 3, |
| "domain": { |
| "filter": "popularity:[5 TO 10]" |
| } |
| } |
| } |
| }' |
| ---- |
| ==== |
| |
| [example.tab-pane#solrj-json-facet-filtered-domain] |
| ==== |
| [.tab-label]*SolrJ* |
| |
| [source,java,indent=0] |
| ---- |
| include::{example-source-dir}JsonRequestApiTest.java[tag=solrj-json-facet-filtered-domain] |
| ---- |
| ==== |
| -- |
| |
| The value of `filter` can be a single query to treat as a filter, or a JSON list of filter queries. Each query can be: |
| |
| * a string containing a query in Solr query syntax. |
| * a reference to a request parameter containing Solr query syntax, of the form: `{param: <request_param_name>}`. |
| The referred parameter might have 0 (absent) or many values. |
| ** When no values are specified, no filter is applied and no error is thrown. |
| ** When many values are specified, each value is parsed and used as filters. |
| |
| When a `filter` option is combined with other `domain` changing options, the filtering is applied _after_ the other domain changes take place. |
| |
| == Filter Exclusions |
| |
| Domains can also be expanded by using the `excludeTags` keyword to discard or ignore particular tagged query filters. |
| |
| This is used in the example below to show the top two manufacturers matching a search. The search results match the filter `manu_id_s:apple`, but the computed facet discards this filter and operates a domain widened by discarding the `manu_id_s` filter. |
| |
| [.dynamic-tabs] |
| -- |
| [example.tab-pane#curl-json-facet-excludetags-domain] |
| ==== |
| [.tab-label]*curl* |
| [source,bash] |
| ---- |
| curl http://localhost:8983/solr/techproducts/query -d ' |
| { |
| "query": "cat:electronics", |
| "filter": "{!tag=MANU}manu_id_s:apple", |
| "facet": { |
| "stock": {"type": "terms", "field": "inStock", "limit": 2}, |
| "manufacturers": { |
| "type": "terms", |
| "field": "manu_id_s", |
| "limit": 2, |
| "domain": { "excludeTags":"MANU" } |
| } |
| } |
| }' |
| ---- |
| ==== |
| |
| [example.tab-pane#solrj-json-facet-excludetags-domain] |
| ==== |
| [.tab-label]*SolrJ* |
| |
| [source,java,indent=0] |
| ---- |
| include::{example-source-dir}JsonRequestApiTest.java[tag=solrj-json-facet-excludetags-domain] |
| ---- |
| ==== |
| -- |
| |
| The value of `excludeTags` can be a single string tag, an array of string tags, or comma-separated tags in the single string. |
| |
| When an `excludeTags` option is combined with other `domain` changing options, it expands the domain _before_ any other domain changes take place. |
| |
| See also the section on <<faceting.adoc#tagging-and-excluding-filters,multi-select faceting>>. |
| |
| == Arbitrary Domain Query |
| |
| A `query` domain can be specified when you wish to compute a facet against an arbitrary set of documents, regardless of the original domain. The most common use case would be to compute a top level facet against a specific subset of the collection, regardless of the main query. But it can also be useful on nested facets when building <<json-facet-api.adoc#relatedness-and-semantic-knowledge-graphs,Semantic Knowledge Graphs>>. |
| |
| Example: |
| |
| [.dynamic-tabs] |
| -- |
| [example.tab-pane#curl-json-facet-query-domain] |
| ==== |
| [.tab-label]*curl* |
| [source,bash] |
| ---- |
| curl http://localhost:8983/solr/techproducts/query -d ' |
| { |
| "query": "apple", |
| "facet": { |
| "popular_categories": { |
| "type": "terms", |
| "field": "cat", |
| "domain": { "query": "popularity:[8 TO 10]" }, |
| "limit": 3 |
| } |
| } |
| }' |
| ---- |
| ==== |
| |
| [example.tab-pane#solrj-json-facet-query-domain] |
| ==== |
| [.tab-label]*SolrJ* |
| |
| [source,java,indent=0] |
| ---- |
| include::{example-source-dir}JsonRequestApiTest.java[tag=solrj-json-facet-query-domain] |
| ---- |
| ==== |
| -- |
| |
| The value of `query` can be a single query, or a JSON list of queries. Each query can be: |
| |
| * a string containing a query in Solr query syntax. |
| * a reference to a request parameter containing Solr query syntax, of the form: `{param: <request_param_name>}`. |
| The referred parameter might have 0 (absent) or many values. |
| ** When no values are specified, no error is thrown. |
| ** When many values are specified, each value is parsed and used as queries. |
| |
| NOTE: While a `query` domain can be combined with an additional domain `filter`, It is not possible to also use `excludeTags`, because the tags would be meaningless: The `query` domain already completely ignores the top-level query and all previous filters. |
| |
| == Block Join Domain Changes |
| |
| When a collection contains <<indexing-nested-documents.adoc#indexing-nested-documents, Nested Documents>>, the `blockChildren` or `blockParent` domain options can be used transform an existing domain containing one type of document, into a domain containing the documents with the specified relationship (child or parent of) to the documents from the original domain. |
| |
| Both of these options work similarly to the corresponding <<other-parsers.adoc#block-join-query-parsers,Block Join Query Parsers>> by taking in a single String query that exclusively matches all parent documents in the collection. If `blockParent` is used, then the resulting domain will contain all parent documents of the children from the original domain. If `blockChildren` is used, then the resulting domain will contain all child documents of the parents from the original domain. |
| |
| [source,json,subs="verbatim,callouts"]] |
| ---- |
| { |
| "colors": { // <1> |
| "type": "terms", |
| "field": "sku_color", // <2> |
| "facet" : { |
| "brands" : { |
| "type": "terms", |
| "field": "product_brand", // <3> |
| "domain": { |
| "blockParent": "doc_type:product" |
| } |
| }}}} |
| ---- |
| <1> This example assumes we parent documents corresponding to Products, with child documents corresponding to individual SKUs with unique colors, and that our original query was against SKU documents. |
| <2> The `colors` facet will be computed against all of the original SKU documents matching our search. |
| <3> For each bucket in the `colors` facet, the set of all matching SKU documents will be transformed into the set of corresponding parent Product documents. The resulting `brands` sub-facet will count how many Product documents (that have SKUs with the associated color) exist for each Brand. |
| |
| == Join Query Domain Changes |
| |
| A `join` domain change option can be used to specify arbitrary `from` and `to` fields to use in transforming from the existing domain to a related set of documents. |
| |
| This works very similar to the <<other-parsers.adoc#join-query-parser,Join Query Parser>>, and has the same limitations when dealing with multi-shard collections. |
| |
| Example: |
| [source,json] |
| ---- |
| { |
| "colors": { |
| "type": "terms", |
| "field": "sku_color", |
| "facet": { |
| "brands": { |
| "type": "terms", |
| "field": "product_brand", |
| "domain" : { |
| "join" : { |
| "from": "product_id_of_this_sku", |
| "to": "id" |
| }, |
| "filter": "doc_type:product" |
| } |
| } |
| } |
| } |
| } |
| |
| ---- |
| |
| == Graph Traversal Domain Changes |
| |
| A `graph` domain change option works similarly to the `join` domain option, but can do traversal multiple hops `from` the existing domain `to` other documents. |
| |
| This works very similar to the <<other-parsers.adoc#graph-query-parser,Graph Query Parser>>, supporting all of it's optional parameters, and has the same limitations when dealing with multi-shard collections. |
| |
| Example: |
| [source,json] |
| ---- |
| { |
| "related_brands": { |
| "type": "terms", |
| "field": "brand", |
| "domain": { |
| "graph": { |
| "from": "related_product_ids", |
| "to": "id", |
| "maxDepth": 3 |
| } |
| } |
| } |
| } |
| ---- |