函數查詢

函數查詢可讓您使用一個或多個數值欄位的實際值來產生相關性分數。

函數查詢使用函數。函數可以是常數(數值或字串文字)、欄位、另一個函數或參數取代引數。您可以使用這些函數來修改使用者結果的排名。這些可用於根據使用者的位置或其他一些計算來變更結果的排名。

使用函數查詢

函數必須表示為函數呼叫(例如,sum(a,b) 而不是簡單的 a+b)。

在 Solr 查詢中有多種使用函數查詢的方式

  • 透過期望函數引數的明確查詢剖析器,例如 funcfrange。例如

    q={!func}div(popularity,price)&fq={!frange l=1000}customer_ratings
  • 在排序運算式中。例如

    sort=div(popularity,price) desc, score desc
  • 將函數的結果以虛擬欄位形式新增至查詢結果中的文件。例如,對於

    &fl=sum(x, y),id,a,b,c,score&wt=xml

    輸出會是

    ...
    <str name="id">foo</str>
    <float name="sum(x,y)">40</float>
    <float name="score">0.343</float>
    ...
  • 在明確用於指定函數的參數中使用,例如 eDisMax 查詢剖析器的 boost 參數,或 DisMax 查詢剖析器的 bf(提升函數)參數。(請注意,bf 參數實際上會採用以空格分隔的函數查詢清單,每個查詢都有一個可選的提升。請務必在使用 bf 時消除單個函數查詢中的任何內部空格)。例如

    q=dismax&bf="ord(popularity)^0.5 recip(rord(price),1,1000,1000)^0.3"
  • 使用 _val_ 關鍵字在 Lucene 查詢剖析器中內嵌引入函數查詢。例如

    q=_val_:mynumericfield _val_:"recip(rord(myfield),1,2,3)"

建議僅使用具有快速隨機存取的函數。

可用的函數

下表總結了可用於函數查詢的函數。

abs 函數

傳回指定值或函數的絕對值。

語法範例

  • abs(x)

  • abs(-5)

childfield(欄位) 函數

在透過 {!parent} 搜尋時,傳回其中一個相符子文件的給定欄位值。它只能在 sort 參數中使用。

語法範例

  • sort=childfield(name) asc 表示 $q 作為第二個引數,因此它假設 q={!parent ..}..

  • sort=childfield(field,$bjq) asc 指的是單獨的參數 bjq={!parent ..}..

  • sort=childfield(field,{!parent of=…​}…​) desc 允許內嵌區塊聯結父查詢

concat 函數

串連給定的字串欄位、文字和其他函數。

語法範例

  • concat(name," ",$param,def(opt,"-"))

"常數" 函數

指定浮點數常數。

語法範例

  • 1.5

def 函數

def 是 default (預設值) 的縮寫。傳回欄位 "field" 的值,如果該欄位不存在,則傳回指定的預設值。產生第一個 exists()==true 的值。

語法範例

  • def(rating,5):這個 def() 函式會傳回評分,如果文件中沒有指定評分,則傳回 5。

  • def(myfield, 1.0): 等同於 if(exists(myfield),myfield,1.0)

div 函式

將一個值或函式除以另一個值或函式。div(x,y)x 除以 y

語法範例

  • div(1,y)

  • div(sum(x,100),max(y,1))

dist 函式

傳回 n 維空間中兩個向量(點)之間的距離。接受冪次,加上兩個或多個 ValueSource 實例,並計算兩個向量之間的距離。每個 ValueSource 都必須是數字。

必須傳入偶數個 ValueSource 實例,且該方法假設前半部分代表第一個向量,後半部分代表第二個向量。

語法範例

  • dist(2, x, y, 0, 0):計算每個文件 (0,0) 和 (x,y) 之間的歐幾里得距離。

  • dist(1, x, y, 0, 0):計算每個文件 (0,0) 和 (x,y) 之間的曼哈頓(計程車)距離。

  • dist(2, x,y,z,0,0,0): 計算每個文件 (0,0,0) 和 (x,y,z) 之間的歐幾里得距離。

  • dist(1,x,y,z,e,f,g):計算 (x,y,z) 和 (e,f,g) 之間的曼哈頓距離,其中每個字母都是欄位名稱。

vectorSimilarity 函式

傳回 n 維空間中兩個 Knn 向量之間的相似度。此函式有兩種變體。

vectorSimilarity(vector1, vector2)

此函式接受兩個向量作為輸入:第一個參數必須是 DenseVectorField 的名稱。第二個參數可以是第二個 DenseVectorField 的名稱,也可以是常數向量。

如果指定了兩個欄位名稱,則它們的配置必須具有相同的 vectorDimensionsvectorEncodingsimilarityFunction。如果指定了常數向量,則會使用第一個參數指定的欄位上配置的 vectorEncoding 來剖析該常數向量,且該常數向量的維度必須相同。

語法範例

  • vectorSimilarity(vectorField1, vectorField2):計算每個文件的向量欄位 vectorField1vectorField2 之間設定的相似度。

  • vectorSimilarity(vectorField1, [1,2,3,4]):計算每個文件的向量欄位 vectorField1[1, 2, 3, 4] 之間設定的相似度。

只有遵循建議的欄位命名慣例的欄位名稱才能保證與此語法搭配使用。在函式查詢中使用時,需要 field("…​") 語法的非典型欄位名稱,必須使用下面描述的 vectorSimilarity(…​) 函式更複雜的 4 個參數變體語法。

vectorSimilarity(ENCODING, SIMILARITY_FUNCTION, vector1, vector2)

輸入向量元素編碼、相似度度量,加上兩個 ValueSource 實例(可以是 DenseVectorField 或常數向量),並計算兩個向量之間的相似度。

  • 支援的編碼有:BYTEFLOAT32

    • 這用於剖析任何常數向量參數

  • 支援的相似度有:EUCLIDEANCOSINEDOT_PRODUCT

語法範例

  • vectorSimilarity(FLOAT32, COSINE, [1,2,3], [4,5,6]):計算每個文件的 [1, 2, 3][4, 5, 6] 之間的餘弦相似度。

  • vectorSimilarity(FLOAT32, DOT_PRODUCT, vectorField1, vectorField2):計算每個文件的 vectorField1vectorField2 中向量之間的點積相似度。

  • vectorSimilarity(BYTE, EUCLIDEAN, [1,5,4,3], vectorField):計算每個文件的 vectorField 中的向量和常數向量 [1, 5, 4, 3] 之間的歐幾里得相似度。

docfreq(field,val) 函式

傳回欄位中包含該詞彙的文件數量。這是一個常數(索引中所有文件的值都相同)。

如果詞彙比較複雜,您可以用引號括住它,或者對詞彙值進行參數替換。

語法範例

  • docfreq(text,'solr')

  • …​&defType=func &q=docfreq(text,$myterm)&myterm=solr

field 函式

傳回具有指定名稱的欄位的數值 docValues 或索引值。以其最簡單的形式(單一參數),此函式只能用於單一值欄位,並且可以使用欄位的名稱作為字串來呼叫,或者對於大多數傳統的欄位名稱,只需使用欄位名稱本身,而無需使用 field(…​) 語法。

使用 docValues 時,可以指定可選的第二個參數來選取多值欄位的 minmax 值。

對於欄位中沒有值的文件,會傳回 0。

語法範例 這 3 個範例都相等

  • myFloatFieldName

  • field(myFloatFieldName)

  • field("myFloatFieldName")

當您的欄位名稱為非典型時,最後一種形式很方便

  • field("my complex float fieldName")

對於多值 docValues 欄位

  • field(myMultiValuedFloatField,min)

  • field(myMultiValuedFloatField,max)

hsin 函式

半正矢距離計算沿球體行進時球體上兩個點之間的距離。這些值必須以弧度表示。hsin 也會接受一個布林參數,指定函式是否應將其輸出轉換為弧度。

語法範例

  • hsin(2, true, x, y, 0, 0)

idf 函式

反向文件頻率;衡量詞彙在所有文件中是常見還是罕見的度量。方法是將文件總數除以包含該詞彙的文件數,然後取該商的對數。另請參閱 tf

語法範例

  • idf(fieldName,'solr'):衡量詞彙 'solr'fieldName 中出現的頻率的反向值。

if 函式

啟用條件函式查詢。在 if(test,value1,value2)

  • test 是一個邏輯值,或參照一個傳回邏輯值(TRUE 或 FALSE)的邏輯值或表達式。

  • 如果 test 產生 TRUE,則 value1 是函式傳回的值。

  • 如果 test 產生 FALSE,則 value2 是函式傳回的值。

表達式可以是任何輸出布林值的函式,甚至是傳回數值的函式,在這種情況下,值 0 將被解釋為 false,或者可以是字串,在這種情況下,空字串將被解釋為 false。

語法範例

  • if(termfreq (cat,'electronics'),popularity,42):此函式檢查每個文件,查看其 cat 欄位中是否包含詞彙「electronics」。如果有,則會傳回 popularity 欄位的值,否則會傳回 42 的值。

linear 函式

實作 m*x+c,其中 mc 是常數,而 x 是任意函式。這等同於 sum(product(m,x),c),但效率更高,因為它是以單一函式實作的。

語法範例

  • linear(x,m,c)

  • linear(x,2,4):傳回 2*x+4

log 函式

傳回指定函式的以 10 為底的對數。

語法範例

  • log(x)

  • log(sum(x,100))

map 函式

將輸入函式 x 的任何值(包含在 minmax 之間)對應到指定的 target。參數 minmax 必須是常數。參數 targetdefault 可以是常數或函式。

如果 x 的值不在 minmax 之間,則會傳回 x 的值,如果指定為第五個參數,則會傳回預設值。

語法範例

  • map(x,min,max,target)

    • map(x,0,0,1):將任何 0 的值變更為 1。這在處理預設的 0 值時可能很有用。

  • map(x,min,max,target,default)

    • map(x,0,100,1,-1):將 0100 之間的任何值變更為 1,將所有其他值變更為 -1

    • map(x,0,100,sum(x,599),docfreq(text,solr)):將 0100 之間的任何值變更為 x+599,將所有其他值變更為欄位 text 中詞彙 'solr' 的頻率。

max 函式

傳回多個巢狀函式或常數的最大數值,這些函式或常數會指定為引數:max(x,y,…​)max 函式對於將另一個函式或欄位「限制」在某些指定的常數也是很有用的。

使用 field(myfield,max) 語法來選取單一多值欄位的最大值

語法範例

  • max(myfield,myotherfield,0)

maxdoc 函式

傳回索引中的文件數量,包括標示為已刪除但尚未清除的文件。這是一個常數(索引中所有文件的值都相同)。

語法範例

  • maxdoc()

min 函式

傳回多個巢狀函式或常數的最小數值,這些函式或常數會指定為引數:min(x,y,…​)min 函式對於使用常數為函式提供「上限」也是很有用的。

使用 field(myfield,min) 語法來選取單一多值欄位的最小值

語法範例

  • min(myfield,myotherfield,0)

ms 函式

傳回引數之間的毫秒差異。日期相對於 Unix 或 POSIX 時間基準,1970 年 1 月 1 日午夜 UTC。

引數可以是 DatePointFieldTrieDateField 的名稱,也可以是基於常數日期或 NOW的日期算術。

  • ms():等同於 ms(NOW),自基準以來的毫秒數。

  • ms(a): 傳回引數所表示的自基準以來的毫秒數。

  • ms(a,b):傳回 b 在 a 之前發生的毫秒數(即 a - b)

語法範例

  • ms(NOW/DAY)

  • ms(2000-01-01T00:00:00Z)

  • ms(mydatefield)

  • ms(NOW,mydatefield)

  • ms(mydatefield, 2000-01-01T00:00:00Z)

  • ms(datefield1, datefield2)

norm(field) 函式

傳回索引中為指定欄位儲存的「norm」。這是索引時間加成和長度正規化因子的乘積,根據該欄位的相似度

語法範例

  • norm(fieldName)

numdocs 函式

傳回索引中文件的數量,不包括那些標記為已刪除但尚未清除的文件。這是一個常數(索引中所有文件的值都相同)。

語法範例

  • numdocs()

ord 函數

傳回在 Lucene 索引順序(按 Unicode 值依字典順序排序)中,索引欄位值在該欄位索引詞彙列表中的序數,從 1 開始。

換句話說,對於給定的欄位,所有值都按字典順序排序;然後此函數傳回特定值在該排序中的偏移量。該欄位每個文件最多只能有一個值(不能是多值)。如果文件中沒有該欄位的值,則傳回 0

ord() 取決於索引中的位置,並且在插入或刪除其他文件時可能會變更。

另請參閱下方的 rord

語法範例

  • ord(myIndexedField)

  • 如果特定欄位 X 只有三個值("apple"、"banana"、"pear"),則對於包含 "apple" 的文件,ord(X) 將為 1,對於包含 "banana" 的文件,則為 2,依此類推。

payload 函數

傳回從指定詞彙的解碼酬載計算出的浮點數值。

傳回值是使用解碼酬載的 minmaxaverage 計算得出的。可以使用特殊的 first 函數來取代其他函數,以短路詞彙列舉並僅傳回第一個詞彙的解碼酬載。

指定的欄位必須具有浮點數或整數酬載編碼功能(透過 DelimitedPayloadTokenFilterNumericPayloadTokenFilter)。如果未找到詞彙的酬載,則傳回預設值。

  • payload(field_name,term):預設值為 0.0,使用 average 函數。

  • payload(field_name,term,default_value):預設值可以是常數、欄位名稱或其他傳回浮點數的函數。使用 average 函數。

  • payload(field_name,term,default_value,function):函數值可以是 minmaxaveragefirst

語法範例

  • payload(payloaded_field_dpf,term,0.0,first)

pow 函數

將指定的底數提高到指定的次方。pow(x,y)x 提高到 y 的次方。

語法範例

  • pow(x,y)

  • pow(x,log(y))

  • pow(x,0.5):sqrt 相同

product 函數

傳回以逗號分隔的清單中指定的多個值或函數的乘積。mul(…​) 也可用作此函數的別名。

語法範例

  • product(x,y,…​)

  • product(x,2)

  • mul(x,y)

query 函數

傳回給定子查詢的分數,或是不符合查詢的文件的預設值。透過參數解參考 $otherparam 或在本機參數中透過 v 鍵直接指定查詢字串,來支援任何類型的子查詢。

語法範例

  • query(subquery, default)

  • q=product (popularity,query({!dismax v='solr rocks'}):傳回 popularity 和 DisMax 查詢分數的乘積。

  • q=product (popularity,query($qq))&qq={!dismax}solr rocks:與先前的查詢等效,使用參數解參考。

  • q=product (popularity,query($qq,0.1))&qq={!dismax}solr rocks:為不符合 DisMax 查詢的文件指定預設分數 0.1。

recip 函數

執行倒數函數,其中 recip(x,m,a,b) 實作 a/(m*x+b),其中 m,a,b 是常數,而 x 是任意複雜的函數。

ab 相等,且 x>=0 時,此函數的最大值為 1,且會隨著 x 的增加而下降。同時增加 ab 的值會導致整個函數移動到曲線的較平坦部分。當 x 為 rord(datefield) 時,這些屬性可以使此函數成為提升較新文件的理想函數。

語法範例

  • recip(myfield,m,a,b)

  • recip(rord (creationDate), 1,1000,1000)

rord 函數

傳回由 ord 傳回的反向排序。

語法範例

  • rord(myDateField)

scale 函數

縮放函數 x 的值,使其落在指定的 minTargetmaxTarget(含)之間。目前的實作會遍歷所有函數值以取得最小值和最大值,因此它可以選擇正確的比例。

目前的實作無法區分文件何時已刪除或文件沒有值。它在這些情況下使用 0.0 值。這表示如果值通常都大於 0.0,則仍然可能以 0.0 作為要對應的 min 值結束。在這些情況下,可以使用適當的 map() 函數作為解決方法,將 0.0 變更為實際範圍中的值,如此處所示:scale(map(x,0,0,5),1,2)

語法範例

  • scale(x, minTarget, maxTarget)

  • scale(x,1,2):縮放 x 的值,使所有值都介於 1 到 2(含)之間。

sqedist 函數

平方歐氏距離計算 2-範數(歐氏距離),但不採用平方根,從而節省了相當昂貴的運算。通常,關注歐氏距離的應用程式不需要實際距離,而是可以使用距離的平方。必須傳入偶數個 ValueSource 實例,並且該方法假設前一半代表第一個向量,後一半代表第二個向量。

語法範例

  • sqedist(x_td, y_td, 0, 0)

sqrt 函數

傳回指定值或函數的平方根。

語法範例

  • sqrt(x)

  • sqrt(100)

  • sqrt(sum(x,100))

strdist 函數

計算兩個字串之間的距離。使用 Lucene 拼字檢查程式 StringDistance 介面,並支援該套件中提供的所有實作,此外還允許應用程式透過 Solr 的資源載入功能插入自己的實作。strdist 接受 (string1, string2, 距離測量)。

距離測量的可能值為

  • jw: Jaro-Winkler

  • edit: Levenshtein 或編輯距離

  • ngram:如果指定,NGramDistance 也可以選擇性地傳入 ngram 大小。預設值為 2。

  • FQN:StringDistance 介面實作的完整限定類別名稱。必須具有無引數建構函式。

語法範例

  • strdist("SOLR",id,edit)

sub 函數

sub(x,y) 傳回 x-y

語法範例

  • sub(myfield,myfield2)

  • sub(100, sqrt(myfield))

sum 函數

傳回以逗號分隔的清單中指定的多個值或函數的總和。add(…​) 也可用作此函數的別名。

語法範例

  • sum(x,y,…​)

  • sum(x,1)

  • sum(sqrt(x),log(y),z,0.5)

  • add(x,y)

sumtotaltermfreq 函數

傳回整個索引中欄位中所有詞彙的 totaltermfreq 值的總和(即,該欄位的索引符號數)。(別名 sumtotaltermfreqsttf。)

語法範例 如果 doc1:(fieldX:A B C) 和 doc2:(fieldX:A A A A)

  • docFreq(fieldX:A) = 2 (A 出現在 2 個文件中)

  • freq(doc1, fieldX:A) = 4 (A 在 doc 2 中出現 4 次)

  • totalTermFreq(fieldX:A) = 5 (A 在所有文件中出現 5 次)

  • sumTotalTermFreq(fieldX) = 7 在 fieldX 中,有 5 個 A、1 個 B、1 個 C

termfreq 函數

傳回詞彙在該文件中欄位中出現的次數。

語法範例

  • termfreq(text,'memory')

tf 函數

詞彙頻率;使用該欄位的 相似度,傳回給定詞彙的詞彙頻率因子。tf-idf 值與單字在文件中出現的次數成比例增加,但會被單字在文件中的頻率抵消,這有助於控制某些單字通常比其他單字更常見的事實。另請參閱 idf

語法範例

  • tf(text,'solr')

top 函數

使函數查詢引數從包含索引所有部分的頂層 IndexReader 取得其值。例如,單個區段中值的序數與完整索引中相同值的序數將不同。

ord()rord() 函數會隱式使用 top(),因此 ord(foo) 等效於 top(ord(foo))

totaltermfreq 函數

傳回詞彙在整個索引中欄位中出現的次數。(別名 totaltermfreqttf。)

語法範例

  • ttf(text,'memory')

布林函數

以下函數是布林函數 – 它們傳回 true 或 false。它們主要用作 if 函數的第一個引數,並且其中一些可以組合。如果在其他地方使用,它將產生 '1' 或 '0'。

and 函數

當且僅當其所有運算元都評估為 true 時,才傳回 true 值。

語法範例

  • and(not(exists(popularity)),exists(price)):對於在 price 欄位中具有值,但在 popularity 欄位中沒有值的任何文件,傳回 true

or 函數

邏輯分離。

語法範例

  • or(value1,value2): 如果 value1value2 為 true,則為 true

xor 函數

邏輯互斥分離,或兩者之一但不同時成立。

語法範例

  • 如果 field1field2 為 true,則 xor(field1,field2) 傳回 true;如果兩者都為 true,則為 FALSE。

not 函數

包裝函數的邏輯否定值。

語法範例

  • not(exists(author)):僅當 exists(author) 為 false 時,才為 true

exists 函數

如果欄位的任何成員存在,則傳回 true

語法範例

  • exists(author):對於在 "author" 欄位中具有值的任何文件,傳回 true

  • exists(query(price:5.00)):如果 "price" 符合 "5.00",則傳回 true

比較函數

gtgteltlteeq

5 個比較函數:大於、大於或等於、小於、小於或等於、等於。eq 不僅適用於數字,還適用於本質上任何值,例如字串欄位。

語法範例

  • if(lt(ms(mydatefield),315569259747),0.8,1) 轉換為此虛擬碼:if mydatefield < 315569259747 then 0.8 else 1

isnan 函數

如果值是浮點數 NaN(非數字),則傳回 true

語法範例

  • isnan(myfield):針對任何在 "myfield" 中儲存 NaN 的文件,回傳 true

  • isnan(12.3456):回傳 false

  • isnan(0):回傳 false

  • isnan(div(0,0)):回傳 true(因為 0 除以 0 未定義,並回傳 NaN)。

函數查詢範例

為了讓您更了解如何在 Solr 中使用函數查詢,假設索引儲存了名為 boxname 的任意名稱的虛擬方塊的長、寬、高(單位為公尺),分別為 x、y、z。假設我們要搜尋名稱為 findbox 的方塊,但根據方塊的體積進行排名。查詢參數將會是:

q=boxname:findbox _val_:"product(x,y,z)"

此查詢會根據體積對結果進行排名。為了取得計算出的體積,您需要請求 score,它將包含產生的體積。

&fl=*, score

假設您還有一個欄位以 weight 儲存方塊的重量。若要根據方塊的密度排序,並在 score 中回傳密度值,您需要提交以下查詢:

https://127.0.0.1:8983/solr/collection_name/select?q=boxname:findbox _val_:"div(weight,product(x,y,z))"&fl=boxname x y z weight score

依函數排序

您可以根據函數的輸出對查詢結果進行排序。例如,若要依距離排序結果,您可以輸入:

https://127.0.0.1:8983/solr/collection_name/select?q=*:*&sort=dist(2, point1, point2) desc

依函數排序也支援偽欄位:欄位可以動態產生,並回傳結果,就像索引中的普通欄位一樣。例如,

&fl=id,sum(x, y),score&wt=xml

會回傳

<str name="id">foo</str>
<float name="sum(x,y)">40</float>
<float name="score">0.343</float>