區塊合併查詢解析器

有兩個查詢解析器支援區塊合併。這些解析器允許為已索引為巢狀文件的關聯內容編製索引和搜尋。

以下查詢解析器的範例用法假設已索引下列文件

<add>
  <doc>
    <field name="id">1</field>
    <field name="content_type">parent</field>
    <field name="title">Solr has block join support</field>
    <doc>
      <field name="id">2</field>
      <field name="content_type">child</field>
      <field name="comments">SolrCloud supports it too!</field>
    </doc>
  </doc>
  <doc>
    <field name="id">3</field>
    <field name="content_type">parent</field>
    <field name="title">New Lucene and Solr release</field>
    <doc>
      <field name="id">4</field>
      <field name="content_type">child</field>
      <field name="comments">Lots of new features</field>
    </doc>
  </doc>
</add>

區塊合併子項查詢解析器

此解析器包裝一個查詢,該查詢比對某些父文件並傳回這些文件的子項。

此解析器的語法為:q={!child of=<blockMask>}<someParents>

  • 內部從屬查詢字串 (someParents) 必須是將比對某些父文件的查詢

  • of 參數必須是查詢字串,以用作區塊遮罩 — 通常是比對所有可能父文件集合的查詢

產生的查詢將比對所有符合 <blockMask> 查詢,並且是由 <someParents> 比對的文件所擁有的子項(或後代)的文件。

使用上述範例文件,我們可以建構一個查詢,例如 q={!child of="content_type:parent"}title:lucene。我們僅收到一個回覆中的文件

<result name="response" numFound="1" start="0">
  <doc>
    <str name="id">4</str>
    <arr name="content_type"><str>child</str></arr>
    <str name="comments">Lots of new features</str>
  </doc>
</result>

someParents 的查詢**必須**符合由 區塊遮罩比對的文件之嚴格子集,否則您的查詢可能會導致錯誤

Parent query must not match any docs besides parent filter.
Combine them as must (+) and must-not (-) clauses to find a problem doc.

如果您遇到這種類型的錯誤,可以搜尋 q=+(someParents) -(blockMask) 來找出原因。

篩選和標記

{!child} 也支援 filtersexcludeTags 等本地參數,如下所示

?q={!child of=<blockMask> filters=$parentfq excludeTags=certain}<someParents>
&parentfq=BRAND:Foo
&parentfq=NAME:Bar
&parentfq={!tag=certain}CATEGORY:Baz

這相當於

q={!child of=<blockMask>}+<someParents> +BRAND:Foo +NAME:Bar

請注意 filters 中用於參考查詢的 "$" 語法;逗號分隔的標記 excludeTags 允許透過標記排除特定查詢。整體而言,概念與排除分面中的 fq類似。請注意,篩選會套用至從屬子句 (<someParents>),且交集結果會加入至子項。

所有子項語法

當省略子句 (<someParents>) 時,它會被解析為子文件的一個分段快取的篩選器。更精確地說,q={!child of=<blockMask>} 等同於 q=*:* -<blockMask>

區塊聯結父查詢解析器

這個解析器接收一個匹配子文件的查詢,並返回它們的父文件。

此解析器的語法與 child 解析器類似:q={!parent which=<blockMask>}<someChildren>

  • 內部子查詢字串 (someChildren) 必須是一個可以匹配某些子文件的查詢。

  • which 參數必須是一個查詢字串,用作區塊遮罩 — 通常是一個匹配所有可能的父文件的查詢。

產生的查詢將會匹配所有確實符合 <blockMask> 查詢,且是 <someChildren> 所匹配的文件之父文件(或祖先)的所有文件。

再次使用上面的範例文件,我們可以建構一個查詢,例如 q={!parent which="content_type:parent"}comments:SolrCloud。我們會收到以下文件作為回應:

<result name="response" numFound="1" start="0">
  <doc>
    <str name="id">1</str>
    <arr name="content_type"><str>parent</str></arr>
    <arr name="title"><str>Solr has block join support</str></arr>
  </doc>
</result>

someChildren 的查詢絕對不能匹配任何被區塊遮罩匹配的文件,否則你的查詢可能會產生錯誤。

Child query must not match same docs with parent filter.
Combine them as must clauses (+) to find a problem doc.

你可以搜尋 q=+(blockMask) +(someChildren) 來找出原因。

篩選和標記

{!parent} 查詢支援 filtersexcludeTags 局部參數,如下所示:

?q={!parent which=<blockMask> filters=$childfq excludeTags=certain}<someChildren>
&childfq=COLOR:Red
&childfq=SIZE:XL
&childfq={!tag=certain}PRINT:Hatched

這相當於

q={!parent which=<blockMask>}+<someChildren> +COLOR:Red +SIZE:XL

請注意 filters 中引用查詢的 "$" 語法。excludeTags 中以逗號分隔的標籤允許通過標記排除某些查詢。總體而言,這個概念與 分面中的排除 fq 相似。請注意,篩選會先應用於子句 (<someChildren>),然後將交集結果聯結到父文件。

使用區塊聯結父查詢解析器進行評分

你可以選擇使用 score 局部參數來返回子查詢的分數。用於此參數的值定義了聚合的類型,可以是 avg (平均值)、max (最大值)、min (最小值)、total (總和)。隱含的預設值是 none,會返回 0.0

所有父文件的語法

當省略子句 (<someChildren>) 時,它會被解析為所有父文件的一個分段快取的篩選器,更精確地說,q={!parent which=<blockMask>} 等同於 q=<blockMask>

區塊遮罩:ofwhich 局部參數

指定為 ofwhich 參數(取決於所使用的解析器)的「區塊遮罩」查詢的目的是識別索引中所有應該被視為「父文件」 *(或其祖先)* 的文件集合,以及哪些文件應該被視為「子文件」。這很重要,因為在「磁碟上」的索引中,關係會被扁平化為「區塊」的文件,因此需要 of / which 參數作為對扁平文件區塊的「遮罩」,以識別每個階層關係的邊界。

在上面的範例查詢中,我們能夠使用非常簡單的 doc_type:parent 區塊遮罩,因為我們的資料非常簡單:每個文件不是 parent 就是 child。因此,這個查詢字串可以輕鬆區分所有文件。

一個常見的錯誤是嘗試使用比所有父文件集合更具限制性的 which 參數,以便篩選匹配的父文件,如這個錯誤範例所示:

// BAD! DO NOT USE!
q={!parent which="title:join"}comments:support

這種查詢通常不會像你預期的那樣工作。由於 which 參數只識別部分「父文件」,產生的查詢可能會匹配到不應該匹配的「父文件」,因為它會錯誤地將所有不匹配 which="title:join" 區塊遮罩的文件識別為索引中下一個「父文件」(符合此遮罩)的子文件。

當將父/子文件與沒有子文件的「簡單」文件混合, *且不匹配用於識別「父」文件的查詢* 時,可能會出現類似的問題。例如,如果我們將以下文件添加到現有的父/子範例文件中:

<add>
  <doc>
    <field name="id">0</field>
    <field name="content_type">plain</field>
    <field name="title">Lucene and Solr are cool</field>
  </doc>
</add>

…​那麼我們簡單的 doc_type:parent 區塊遮罩將不再足夠。我們需要使用 *:* -doc_type:childdoc_type:(simple parent) 來防止我們的「簡單」文件被錯誤地視為相鄰「父」文件的「子文件」。

搜尋巢狀子文件 章節包含更多關於使用非簡單文件階層指定區塊遮罩查詢的詳細範例。