JSON 请求 API

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

构建 JSON 请求

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

  • curl

  • SolrJ

curl https://127.0.0.1:8983/solr/techproducts/query -d '
{
  "query" : "memory",
  "filter" : "inStock:true"
}'
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 https://127.0.0.1:8983/solr/techproducts/query -d 'json={"query":"memory"}'

JSON 参数合并

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

JSON 请求 API 有几个属性(`filter`、`fields` 等)接受多个值。在合并过程中,这些“多值”属性的所有值都将被保留。但是,许多属性(`query`、`limit` 等)只能有一个值。当多个参数值相互冲突时,将根据以下优先级规则选择单个值

  • 传统的查询参数(`q`、`rows` 等)具有最高优先级,并且优先于任何其他指定的值。

  • `json`-前缀的查询参数被认为是下一个。

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

这种分层合并提供了两全其美的效果。可以使用可读的结构化 JSON 指定请求。但是,用户也可以灵活地分离出经常更改的请求部分。这可以在以下示例中看到,该示例结合了 `json.` 样式的参数来覆盖和补充主 JSON 正文中找到的值。

  • curl

  • SolrJ

curl 'https://127.0.0.1:8983/solr/techproducts/query?json.limit=5&json.filter="cat:electronics"' -d '
{
  query: "memory",
  limit: 10,
  filter: "inStock:true"
}'
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

  • SolrJ

curl https://127.0.0.1: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.
}'
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

  • SolrJ

curl https://127.0.0.1:8983/solr/techproducts/query -d 'q=*:*&rows=1&
  json.facet.avg_price="avg(price)"&
  json.facet.top_cats={type:terms,field:"cat",limit:3}'
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

  • SolrJ

curl https://127.0.0.1:8983/solr/techproducts/query -d '
{
  "query": "*:*",
  "limit": 1,
  "facet": {
    "avg_price": "avg(price)",
    "top_cats": {
      "type": "terms",
      "field": "cat",
      "limit": 5
    }
  }
}
'
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

  • SolrJ

curl "https://127.0.0.1:8983/solr/techproducts/query?fl=name,price"-d '
{
  params: {
    q: "memory",
    rows: 1
  }
}'
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 "https://127.0.0.1:8983/solr/techproducts/query?fl=name,price&q=memory&rows=1"

queries 键的用法在 附加查询 中描述。

参数替换/宏展开

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

  • curl

  • SolrJ

curl "https://127.0.0.1:8983/solr/techproducts/query?FIELD=text&TERM=memory" -d '
{
  query:"${FIELD}:${TERM}",
}'
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 facets 没有影响。