JSON 请求 API

Solr 支持一个备用请求 API,它接受部分或全部由 JSON 对象组成的请求。在某些情况下,此备用 API 可能更可取,因为其可读性和灵活性更高,使其比完全由查询参数驱动的备用 API 更易于使用。还有一些功能只能通过此 JSON 请求 API 访问,例如 JSON 分面 API 的大部分分析功能。

构建 JSON 请求

JSON 请求 API 的核心是其将请求参数指定为请求正文中的 JSON 的能力,如下例所示

curl

curl http://localhost:8983/solr/techproducts/query -d '
{
  "query" : "memory",
  "filter" : "inStock:true"
}'

SolrJ

final JsonQueryRequest simpleQuery =
    new JsonQueryRequest().setQuery("memory").withFilter("inStock:true");
QueryResponse queryResponse = simpleQuery.process(solrClient, COLLECTION_NAME);

JSON 对象通常在请求正文中发送,但也可以作为 json 前缀查询参数的值发送。这可用于覆盖或补充请求正文中指定的值。例如,查询参数 json.limit=5 将覆盖 JSON 请求正文中提供的任何 limit 值。您还可以在单个 json 查询参数中指定整个 JSON 正文,如下例所示

curl http://localhost:8983/solr/techproducts/query -d 'json={"query":"memory"}'

JSON 参数合并

如果在单个请求中提供了多个 json 参数,Solr 会尝试在处理请求之前将参数值合并在一起。

JSON 请求 API 具有几个属性(filterfields 等),它们接受多个值。在合并过程中,将保留这些“多值”属性的所有值。然而,许多属性(querylimit 等)只能有一个值。当多个参数值相互冲突时,将根据以下优先级规则选择一个值

  • 传统查询参数(qrows 等)优先级最高,并优先于任何其他指定值。

  • 接下来考虑以 json 为前缀的查询参数。

  • 在 JSON 请求正文中指定的值优先级最低,仅在其他任何地方未指定时才使用。

这种分层合并方式兼顾了两种方式的优点。可以使用可读的结构化 JSON 来指定请求。但用户还可以灵活地分离出经常更改的请求部分。以下示例中可以看到这一点,该示例结合了 json. 样式的参数来覆盖和补充在主 JSON 正文中找到的值。

curl

curl 'http://localhost:8983/solr/techproducts/query?json.limit=5&json.filter="cat:electronics"' -d '
{
  query: "memory",
  limit: 10,
  filter: "inStock:true"
}'

SolrJ

final ModifiableSolrParams overrideParams = new ModifiableSolrParams();
final JsonQueryRequest queryWithParamOverrides =
    new JsonQueryRequest(overrideParams)
        .setQuery("memory")
        .setLimit(10)
        .withFilter("inStock:true");
overrideParams.set("json.limit", 5);
overrideParams.add("json.filter", "\"cat:electronics\"");
QueryResponse queryResponse = queryWithParamOverrides.process(solrClient, COLLECTION_NAME);

这等同于

curl

curl http://localhost:8983/solr/techproducts/query -d '
{
  "query": "memory",
  "limit": 5,     // this single-valued parameter was overwritten.
  "filter": ["inStock:true","cat:electronics"]    // this multi-valued parameter was appended to.
}'

SolrJ

final JsonQueryRequest query =
    new JsonQueryRequest()
        .setQuery("memory")
        .setLimit(5)
        .withFilter("inStock:true")
        .withFilter("cat:electronics");
QueryResponse queryResponse = query.process(solrClient, COLLECTION_NAME);

同样,智能合并可用于创建根本没有正确请求正文的 JSON API 请求,例如以下示例

curl

curl http://localhost:8983/solr/techproducts/query -d 'q=*:*&rows=1&
  json.facet.avg_price="avg(price)"&
  json.facet.top_cats={type:terms,field:"cat",limit:3}'

SolrJ

final ModifiableSolrParams params = new ModifiableSolrParams();
final SolrQuery query = new SolrQuery("*:*");
query.setRows(1);
query.setParam("json.facet.avg_price", "\"avg(price)\"");
query.setParam("json.facet.top_cats", "{type:terms,field:\"cat\",limit:3}");
QueryResponse queryResponse = solrClient.query(COLLECTION_NAME, query);

这等同于以下请求

curl

curl http://localhost:8983/solr/techproducts/query -d '
{
  "query": "*:*",
  "limit": 1,
  "facet": {
    "avg_price": "avg(price)",
    "top_cats": {
      "type": "terms",
      "field": "cat",
      "limit": 5
    }
  }
}
'

SolrJ

final JsonQueryRequest jsonQueryRequest =
    new JsonQueryRequest()
        .setQuery("*:*")
        .setLimit(1)
        .withStatFacet("avg_price", "avg(price)")
        .withFacet("top_cats", new TermsFacetMap("cat").setLimit(3));
QueryResponse queryResponse = jsonQueryRequest.process(solrClient, COLLECTION_NAME);

有关分面和分析命令的更多信息,请参见 JSON 分面 API

支持的属性和语法

目前,Solr 的一些传统查询参数才具有同等级别的 JSON 等效项。这些参数如下表所示

表 1. 标准查询参数到 JSON 字段
查询参数 同等级别的 JSON 字段

q

query

fq

filter

start

offset

rows

limit

fl

fields

sort

sort

json.facet

facet

json.<param_name>

<param_name>

json.queries.<query_name>

queries

上表中未指定的参数仍可用于 JSON API 请求的主体中,但它们必须放在 params 块中,如下面的示例所示。

curl

curl "http://localhost:8983/solr/techproducts/query?fl=name,price"-d '
{
  params: {
    q: "memory",
    rows: 1
  }
}'

SolrJ

final ModifiableSolrParams params = new ModifiableSolrParams();
params.set("fl", "name", "price");
final JsonQueryRequest simpleQuery =
    new JsonQueryRequest(params).withParam("q", "memory").withParam("rows", 1);
QueryResponse queryResponse = simpleQuery.process(solrClient, COLLECTION_NAME);

放置在 params 块中的参数的作用就像将它们原样添加到请求的查询参数中。上面的请求等同于

curl "http://localhost:8983/solr/techproducts/query?fl=name,price&q=memory&rows=1"

其他查询 中描述了 queries 键的用法。

参数替换/宏扩展

当然,通过参数替换进行请求模板化也完全适用于 JSON 请求正文或参数。例如

curl

curl "http://localhost:8983/solr/techproducts/query?FIELD=text&TERM=memory" -d '
{
  query:"${FIELD}:${TERM}",
}'

SolrJ

final ModifiableSolrParams params = new ModifiableSolrParams();
params.set("FIELD", "text");
params.set("TERM", "memory");
final JsonQueryRequest simpleQuery = new JsonQueryRequest(params).setQuery("${FIELD}:${TERM}");
QueryResponse queryResponse = simpleQuery.process(solrClient, COLLECTION_NAME);

JSON 扩展

Solr 在其请求 API 中使用 Noggit JSON 解析器。Noggit 能够进行更宽松的 JSON 解析,并允许对 JSON 标准进行一些修改

  • 裸词可以不加引号

  • 可以使用 //# 插入单行注释

  • 可以使用 /**/ 插入多行(“C 样式”)注释

  • 字符串可以使用单引号

  • 特殊字符可以使用反斜杠转义

  • 尾随(额外)逗号会被自动忽略(例如,[9,4,3,]

  • nbsp(不换行空格,\u00a0)被视为空白。

调试

如果您想要查看合并/解析的 JSON 的样子,您可以打开调试(debug=timing),它将与其他调试信息一起在“json”键下返回。请注意,debug=truedebugQuery=true 通常会对性能产生重大影响,并且应该保留用于调试。另外请注意,debug=query 对 SolrCloud 中的 JSON 分面没有影响。