Solr Reference Guide 5.3: Searching

Overview of Searching in Solr

當使用者在 Solr 執行一個 search,這個 search query 是由一個 request handler 來處理。

這個 request handler 是一個 Solr plug-in,它定義當 Solr 處理 request 時的邏輯。

Solr 支援各種 request handlers,有些是設計來處理 search queries,有些是用來管理像 index replication 這樣的工作。

Search applications 預設會選擇一個特定的 request handler。

也可以設定成使用另一個不同的 request handler。

要處理 search query,request handler 會呼叫一個 query parser,它解讀 query 裡面的詞彙以及參數。

不同的 query parsers 支援不同的語法。

預設的 query parser 是 DisMax query parser。

Solr 也句含了一個早期「標準」(Lucene) 的 query parser,以及一個 Extended DisMax (eDisMax) query parser。

標準 query parser 的語法有較高的搜尋精準度,但是 DisMax query parser 的容錯能力好很多。

DisMax query parser 的設計目的是要提供類似 Google 等流行搜尋引擎的使用經驗,它們很少會跟使用者說有什麼語法錯誤。

Extended DisMax query parser 則是 DisMax 的加強版,它能處理全部 Lucene 的 query 語法,同時能容忍語法錯誤。它也包含一些額外的功能。

輸入到 query parser 的東西可以包含這些:

  • 搜尋字串:也就是要在索引中尋找的字詞
  • 微調查詢的參數:增加某個特定字串或 field 的重要性,在字詞之間使用布林邏輯運算,或者從搜尋結果中排除某些內容。
  • 控制 query response 呈現的參數:例如排序的方式,或者限制回傳某些特定的 fields。

搜尋參數也可以指定一個 query filter。Query filter 會對整個索引執行一個 query,並將結果 cache 起來。

因為 Solr 會分配一個隔離的 cache 給 filter queries 用,使用 filter queries 的策略可以增進搜尋的效能。

(注意 query filters 跟 analysis filters 是不一樣的東西)

Search query 可以要求在 search response 裡的某些字詞要 highlighted,

也就是說,這些選擇的字詞會用有顏色的框框呈現,使用它們從搜尋結果之中突顯出來。

Hinglighting 使得在回傳的長文件之中容易找到相關的文字區段。

Solr 支援多字詞的 highlighting。

Solr 包含了多個 search parameters 可以用來控制字詞要如何做 highlight。

可以設定 search responses 要包含 snippets (文件節錄),而且關鍵字做 highlight。

像 Google、Yahoo! 這些流行的搜尋引擎,它們的搜尋結果中都會回傳 snippets:三到四行的文字,提供了搜尋結果的描述。

為了幫助使用者將注意力集中在他們所要尋找的東西上,

Solr 支援 faceting 以及 clustering 這兩種將搜尋結果做分組的特殊方式,以此輔助進一步的探索。

Faceting 是將搜尋結果分為多個類型(基於索引字詞)的整理方式。

對於每一個類型,Solr 會報告符合相關字詞的 hit 筆數,這個相關字詞稱為 facet constraint。

Faceting 讓使用者在電影網站或產品檢視網站上,更容易探索搜尋結果,在這些網站上有多個類別,每個類別裡有多個項目。

下圖顯示 CNET 網站的 faceting 範例:

Faceting 使用的是在建索引時就定義好了的 fields。在上例中,這些 fields 包括了描述數位相機的:廠商、解析度、變焦範圍。

Clustering 則是在搜尋被執行的時候,依照所發現的相似性將搜尋結果做分群,而不是依照建索引時就定好的內容。

Clustering 的結果通常缺少 faceted search results 的整齊階層組織,不過 clustering 仍然是有用的。

它可以在搜尋結果之間找出意料之外的共通性,而且它可以幫助使用者排除與他們真正要找的東西不相關的資料。

Solr 也提供一個功能稱為 MoreLikeThis,它讓使用者提出一個新的 query,這個 query 集中在之前查詢回傳之中的特定字詞。

MoreLikeThis 可以使用 faceting 或 clustering 來提供額外的幫助給使用者。

下圖摘要搜尋程序的一些關鍵元素:

Velocity Search UI

Solr 包含一個基於 VelocityResponseWriter (也稱為 Solritas) 的 search UI 範例,它展示了幾個有用的功能,例如搜尋、faceting、highlighting、autocomplete 以及 geospatial 搜尋。

當你使用 sample_techproducts_configs 這個 config set,你可以從這裡存取 Velocity sample Search UI:http://localhost:8983/solr/techproducts/browse

Relevance

Relevance 是查詢結果滿足使用者的程度。

一個 query response 的 relevance 視提出查詢所處的情境而定。

同一個 search application,可能由不同需求和期望的使用者在不同的情境中使用。

例如一個氣象資料的搜尋引擎,使用者可能是研究氣候趨勢的大學研究者;也可能是一個農夫,他的興趣是計算春季最後一個霜凍的可能日期;或是一個土木工程師,他的興趣是降雨模式以及洪水頻率;或是一個準備到某個地區渡假的大學生,他不知道該帶些什麼。

因為這些使用者動機的不同,任何特定查詢回應的 relevance 也會跟著改變。

How comprehensive should query responses be? Like relevance in general, the answer to this question depends on the context of a search. The cost of not finding a particular document in response to a query is high in some contexts, such as a legal e-discovery search in response to a subpoena, and quite low in others, such as a search for a cake recipe on a Web site with dozens or hundreds of cake recipes. When configuring Solr, you should weigh comprehensiveness against other factors such as timeliness and ease-of-use.

關於 relevance 的兩個重要觀念:

  • Precision:回傳結果之中有多少百分比是 relevant。
  • Recall:系統中所有的 relevant 結果有多少百分比被回傳回來。得到完美的 recall 很簡單,每個 query 都傳回全部文件就好了。

回到上面的例子,對於一個 e-discovery 搜尋應用軟體來說,回傳與某張傳票有關的所有文件,以此達到 100% 的 recall,這是很重要的。

而對於一個食譜應用軟體來說,就沒那麼重要了。

在一些非正式的情境下,回傳太多結果可能會讓使用者不知所措。

在某些情境下,回傳少一點的結果,但是有更高的相關相似度,這可能是最好的辦法。\

Query Syntax and Parsing

Common Query Parameters

Standard, DisMax, 以及 eDisMax 等 Request Handlers 都支援的共通參數。

defType

defType 參數選擇 Solr 要用哪個一毎 query parser 來處理 request 裡主要的 query parameter (q) 。

例如:

defType=dismax

如果沒有指定 defType 參數,預設是使用 Standard Query Parser。(eg: defType=lucene)

sort

在 URL 裡 escape 為 score+desc 或 score%20desc

多個排序項目時以半形逗點隔開:

sort=<field name>+<direction>,<field name>+<direction>],...

start

指定由某個 offset 開始回傳,預設是 0.

rows

一次最多回傳幾筆,預設為 10.

fq (Filter Query)

fq 參數定義一個 query 用來限制哪些文件可以回傳,不影響 score。

它對於加速複雜的 queries 很有用,因為 fq 指定的 query 會暫存在另一個地方。

之後如果另一個 query 用到相同的 filter,會很快由暫存區回傳。

使用 fq 參數的時候,記得下面這些事:

  • 在一個 query 裡可以指定 fq 參數多次。在這多個參數的交集中的文件才會回傳。下例之中,只有 popularity 大於 10 而且 section 是 0 的文件才會回傳:
fq=popularity:[10 TO *]&fq=section:0
  • Filter queries 可以包含複雜的邏輯運算。上面的例子也可以寫成一個 fq 裡面有兩個命令子句:
fq=+popularity:[10 TO *] +section:0
  • 每一個 filter query 的文件集合會獨立暫存。考慮上面的例子:使用一個 fq 包含兩個命令子句,如果它們經常同時出現;使用兩個分開的 fq 參數,如果它們彼此之間沒什麼關係。(關於調整暫存區的大小,以及確認某個 filter 暫存是否真的存在,參見:The Well-Configured Solr Instance.)
  • 跟所有的其他參數一樣:URL 裡的特殊字元要 escape,有一些線上工具可以幫忙,例如:http://meyerweb.com/eric/tools/dencoder/

fl (Field List)

fl 參數限制 query response 中的資訊只包含指定的 fields。

這些 fields 必須索引為 stored,這個參數才能正確運作。

這個 field 清單的多個 field 名稱之間可由空格或逗點區隔。

"score" 這個字串可以用來指定某次 query 中,每個文件的 score 當做一個 field 回傳。

萬用字元 "*" 選取文件中所有 stored fields。

你也可以在 field 清單中增加 psuedo-fields, functions 以及 transformers。

如何使用 fl 的基本範例:

Function Values

每個回傳的文件,都可以用函數運算,然後以 psuedo-field 回傳:

fl=id,title,product(price,popularity)

Document Transformers

Document Transformers 可以用來修改回傳的資訊:

fl=id,title,[explain]

Field Name Aliases

在 field, 函數 或 transformer 前加上 「displayName:」可以變更它們的 key。例如:

fl=id,sales_price:price,secret_sauce:prod(price,popularity),why_score:[explain style=nl]

回傳:

"response": { "numFound":2, "start":0, "docs":[

{

"id":"6H500F0",

"secret_sauce":2100.0,

"sales_price":350.0,

"why_score":{

"match":true,

"value":1.052226,

"description":"weight(features:cache in 2) [DefaultSimilarity], result of:",

"details":[{

...

debug

debug 參數可以指定多次,並支援下列引數:

  • debug=query:只回傳關於 query 的 debug 資訊。
  • debug=timing:回傳關於 query 使用時間的 debug 資訊。
  • debug=result:回傳關於 score results 的 debug 資訊(也稱為 "explain")
  • debug=all:回傳關於 request 的所有可用 debug 資訊。(另外用法:debug=true)

預設不會有 debug 資訊。

explainOther

PDF Page: 230

The explainOther parameter specifies a Lucene query in order to identify a set of documents. If this parameter is included and is set to a non-blank value, the query will return debugging information, along with the "explain info" of each document that matches the Lucene query, relative to the main query (which is specified by the q parameter). For example:

q=supervillians&debugQuery=on&explainOther=id:juggernaut

The query above allows you to examine the scoring explain info of the top matching documents, compare it to the explain info for documents matching id:juggernaut, and determine why the rankings are not as you expect.

這個參數的預設值是空的,沒有額外的 "explain info" 會回傳。

timeAllowed

這個參數指定一個搜尋允許的時間,以 millisecond 為單位。

如果時間到了而搜尋還沒有完成,會回傳已搜尋到的部份結果。

omitHeader

這個參數可以設成 true 或 false。

如果設成 true,回傳結果會排除 header。

Header 包含關於 request 的資訊,例如完成所花費的時間。

這個參數的預設值是 false。

wt

wt 參數告訴 Solr 要選擇哪個 Response Writer 用來將 query's responese 做格式化。

詳見:Response Writers.

cache=false

Solr 預設會暫存所有 queries 以及 filter queries 的結果。

要取消結果暫存,可以設定 cache=false 參數。

You can also use the cost option to control the order in which non-cached filter queries are evaluated. This allows you to order less expensive non-cached filters before expensive non-cached filters.

For very high cost filters, if cache=false and cost>=100 and the query implements the PostFilter interface, a Collector will be requested from that query and used to filter documents after they have matched the main query and all other filter queries. There can be multiple post filters; they are also ordered by cost.

PDF Page: 231

For example:

// normal function range query used as a filter, all matching documents 
// generated up front and cached 
fq={!frange l=10 u=100}mul(popularity,price) 
// function range query run in parallel with the main query like a traditional 
// lucene filter 
fq={!frange l=10 u=100 cache=false}mul(popularity,price) 
// function range query checked after each document that already matches the query 
// and all other filters. Good for really expensive function queries. 
fq={!frange l=10 u=100 cache=false cost=100}mul(popularity,price)

logParamsList

Solr 預設會把 requests 的所有參數都寫到 log 裡。

從 4.7 版開始,設定這個參數可以限制哪些參數要寫到 log 裡。

這可以幫助控制只記錄你認為重要的參數。

例如,你可以這麼定義:

logParamsList=q,fq

這樣就只有 'q' 和 'fq' 這兩個參數會被記錄下來。

如果任何參數都不記錄,那麼你可以送一個空的 logParamsList (也就是 logParamsList=)。

這個參數不只用在 query requests,而是可以用在 Solr 任何類型的 requests.

The Standard Query Parser

Solr 預設的 Query Parser 也被稱為 "lucene" parser。

Standard query parser 的關鍵優勢是它支援健全而且相當直覺的語法,讓你可以建立各種結構化查詢。

最大的缺點是,它對於語法錯誤的容忍度很低,相較之下,像 DisMax 這種 query parser 的設計目標是儘可能不要回傳錯誤。

Standard Query Parser Parameters

除了共用的 Query 參數、Faceting 參數、Highlighting 參數,以及 MoreLikeThis 參數之外,standard query parser 支援下表中的參數:

預設的參數值在 solrconfig.xml 中指定,或者在 request 執行查詢時可以被覆寫。

PDF Page: 232

The Standard Query Parser's Response

預設從 standard query parser 回傳的 response 裡包含一個沒有名稱的 <result> 區塊。

如果使用 debug 參數,那麼會回傳一個額外的 <lst> 區塊,名稱叫做 "debug"。

這包含有用的除錯資訊,包括原始查詢字串,parse 過的查詢字串,以及 <result> 區塊中每一個文件的 explain info。

如果也使用了 explainOther 參數,那麼符合查詢的全部文件都會有額外的 explain info。

Sample Responses

這個小節展示由 standard query parser 回傳的 response 範例。

下面的 URL 送出一個簡單的 query,並要求 XML Response Writer 使用內縮讓 XML response 更具可讀性。

http://localhost:8983/solr/techproducts/select?q=id:SP2514N

結果:

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <responseHeader><status>0</status><QTime>1</QTime></responseHeader>
  <result numFound="1" start="0">
    <doc>
      <arr name="cat">
        <str>electronics</str>
        <str>hard drive</str>
      </arr>
      <arr name="features">
        <str>7200RPM, 8MB cache, IDE Ultra ATA-133</str>
        <str>NoiseGuard, SilentSeek technology, Fluid Dynamic Bearing (FDB) motor</str>
      </arr>
      <str name="id">SP2514N</str>
      <bool name="inStock">true</bool>
      <str name="manu">Samsung Electronics Co. Ltd.</str>
      <str name="name">Samsung SpinPoint P120 SP2514N - hard drive - 250 GB -
ATA-133</str>
      <int name="popularity">6</int>
      <float name="price">92.0</float>
      <str name="sku">SP2514N</str>
    </doc>
  </result>
</response>

限制 field 清單的查詢範例:

http://localhost:8983/solr/techproducts/select?q=id:SP2514N&fl=id+name

結果:

PDF Page: 233

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <responseHeader><status>0</status><QTime>2</QTime></responseHeader>
  <result numFound="1" start="0">
    <doc>
      <str name="id">SP2514N</str>
      <str name="name">Samsung SpinPoint P120 SP2514N - hard drive - 250 GB -
ATA-133</str>
    </doc>
  </result>
</response>