JSON 分面域更改

切面计算在文档的“域”上进行操作。默认情况下,此域由主查询匹配的文档组成。对于子切面,域由父切面放入其存储段中的所有文档组成。

用户还可以使用显式 domain 属性覆盖对数据进行分区的切面的“域”,其值是一个 JSON 对象,该对象可以支持在为关联切面计算存储段之前限制、扩展或完全更改原始域的各种选项。

domain 更改只能在对数据进行分区(而不是统计/度量切面或切面组)的各个切面上指定。

具有 domain 更改的 *:* 查询切面可用于对任何类型的多个子切面进行分组,以便应用通用域更改。

添加域过滤器

域更改的最简单示例是指定将应用于现有域的附加过滤器。这可以通过切面的 domain 块中的 filter 关键字来完成。

curl

curl http://localhost:8983/solr/techproducts/query -d '
{
  "query": "*:*",
  "facet": {
    "categories": {
      "type": "terms",
      "field": "cat",
      "limit": 3,
      "domain": {
        "filter": "popularity:[5 TO 10]"
      }
    }
  }
}'

SolrJ

final TermsFacetMap categoryFacet =
    new TermsFacetMap("cat")
        .setLimit(3)
        .withDomain(new DomainMap().withFilter("popularity:[5 TO 10]"));
final JsonQueryRequest request =
    new JsonQueryRequest().setQuery("*:*").withFacet("categories", categoryFacet);
QueryResponse queryResponse = request.process(solrClient, COLLECTION_NAME);

filter 的值可以是作为过滤器处理的单个查询,也可以是过滤器查询的 JSON 列表。每个查询可以是

  • 包含 Solr 查询语法中查询的字符串。

  • 对包含 Solr 查询语法的请求参数的引用的形式:{param: <request_param_name>}。可以在 JSON 请求 API 中 queries 键下定义的 DSL 语法中引用一个或多个查询。引用的参数可能具有 0(不存在)或多个值。

    • 未指定任何值时,不应用过滤器且不引发错误。

    • 指定多个值时,每个值都会被解析并用作结合的过滤器。

以下是引用 DSL 查询的示例

curl http://localhost:8983/solr/techproducts/query -d '
{
  "query": "*:*",
  "queries": {
      "sample_filtrs":[
           {"field":{"f":"text", "query":"usb"}},
           {"field":{"f":"text", "query":"lcd"}}
        ],
        "another_filtr":
            {"field":{"f":"text", "query":"usb"}}
  },
  "facet": {
    "usblcd": {
      "type": "terms",
      "field": "cat",
      "limit": 3,
      "domain": {
        "filter": {"param":"sample_filtrs"}
      }
    },
    "justusb": {
      "type": "terms",
      "field": "cat",
      "limit": 3,
      "domain": {
        "filter": {"param":"another_filtr"}
      }
    }
  }
}'

filter 选项与其他 domain 更改选项结合使用时,将在执行其他域更改之后应用过滤。

过滤器排除

还可以使用 excludeTags 关键字来丢弃或忽略特定标记的查询过滤器,从而扩展域。

以下示例中使用了此方法,以显示与搜索匹配的前两个制造商。搜索结果与过滤器 manu_id_s:apple 匹配,但计算出的切面会丢弃此过滤器并通过丢弃 manu_id_s 过滤器来操作扩展的域。

curl

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" }
    }
  }
}'

SolrJ

final TermsFacetMap inStockFacet = new TermsFacetMap("inStock").setLimit(2);
final TermsFacetMap allManufacturersFacet =
    new TermsFacetMap("manu_id_s")
        .setLimit(2)
        .withDomain(new DomainMap().withTagsToExclude("MANU"));
final JsonQueryRequest request =
    new JsonQueryRequest()
        .setQuery("cat:electronics")
        .withFilter("{!tag=MANU}manu_id_s:apple")
        .withFacet("stock", inStockFacet)
        .withFacet("manufacturers", allManufacturersFacet);
QueryResponse queryResponse = request.process(solrClient, COLLECTION_NAME);

excludeTags 的值可以是单个字符串标记、字符串标记数组或单个字符串中的逗号分隔标记。

excludeTags 选项与其他 domain 更改选项结合使用时,它会在执行任何其他域更改之前扩展域。

另请参阅有关 多选分面 的部分。

任意域查询

当您希望针对任意一组文档计算分面时,无论原始域如何,都可以指定 query 域。最常见的用例是针对集合的特定子集计算顶级分面,而不管主查询如何。但在构建 语义知识图 时,在嵌套分面中它也可能很有用。

示例

curl

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
    }
  }
}'

SolrJ

final TermsFacetMap inStockFacet = new TermsFacetMap("inStock").setLimit(2);
final TermsFacetMap popularCategoriesFacet =
    new TermsFacetMap("cat")
        .withDomain(new DomainMap().withQuery("popularity:[8 TO 10]"))
        .setLimit(3);
final JsonQueryRequest request =
    new JsonQueryRequest()
        .setQuery("apple")
        .withFacet("popular_categories", popularCategoriesFacet);
QueryResponse queryResponse = request.process(solrClient, COLLECTION_NAME);

query 的值可以是单个查询,或查询的 JSON 列表。每个查询可以是

  • 包含 Solr 查询语法中查询的字符串。

  • 对包含 Solr 查询语法的请求参数的引用,格式为:{param: <request_param_name>}。引用的参数可能具有 0(不存在)或多个值。

    • 未指定任何值时,不会引发错误。

    • 指定多个值时,将解析每个值并用作查询。

虽然 query 域可以与附加域 filter 结合使用,但不能同时使用 excludeTags,因为标签将毫无意义:query 域已经完全忽略了顶级查询和所有先前的过滤器。

阻止连接域更改

当集合包含 嵌套文档 时,blockChildrenblockParent 域选项可用于将包含一种类型文档的现有域转换为包含与原始域中的文档具有指定关系(子文档或父文档)的文档的域。

这两个选项的工作方式类似于相应的 阻止连接查询解析器,通过采用一个专门匹配集合中所有父文档的字符串查询。如果使用 blockParent,则生成的域将包含原始域中子文档的所有父文档。如果使用 blockChildren,则生成的域将包含原始域中父文档的所有子文档。通常需要在父文档中计算子文档的分面,这可以通过 uniqueBlock(_root_) 完成,如 阻止连接分面计数 中所述。

{
  "colors": {                         (1)
    "type": "terms",
    "field": "sku_color",             (2)
    "facet" : {
      "brands" : {
        "type": "terms",
        "field": "product_brand",     (3)
        "domain": {
          "blockParent": "doc_type:product"
        }
      }}}}
1 此示例假定我们有与产品对应的父文档,与具有唯一颜色的各个 SKU 对应的子文档,并且我们的原始查询针对 SKU 文档。
2 colors 分面将针对所有匹配我们搜索的原始 SKU 文档计算。
3 对于 colors 分面的每个存储桶,所有匹配的 SKU 文档的集合将转换成相应的父级产品文档的集合。结果的 brands 子分面将统计每个品牌有多少产品文档(具有与关联颜色相关的 SKU)。

联接查询域更改

join 域更改选项可用于指定任意 fromto 字段,以便从现有域转换成一组相关的文档。

这与 联接查询解析器 的工作方式类似,并且在处理多片键集合时具有相同的限制。

示例

{
  "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"
        }
      }
    }
  }
}

join 域更改支持一个可选的 method 参数,该参数允许用户指定他们希望在此域转换中使用的联接实现。Solr 提供了多种联接实现,每种实现都具有不同的性能特征。有关这些实现及其权衡的详细信息,请参阅 method 参数文档。联接域更改支持除 crossCollection 之外的所有 method 值。

图遍历域更改

graph 域更改选项的工作方式与 join 域选项类似,但可以从现有域 to 其他文档遍历多个跃点。

这与 图查询解析器 的工作方式非常相似,支持其所有可选参数,并且在处理多片键集合时具有相同的限制。

示例

{
  "related_brands": {
    "type": "terms",
    "field": "brand",
    "domain": {
      "graph": {
        "from": "related_product_ids",
        "to": "id",
        "maxDepth": 3
      }
    }
  }
}