函數查詢
函數查詢可讓您使用一個或多個數值欄位的實際值來產生相關性分數。
DisMax 查詢剖析器、擴展 DisMax (eDisMax) 查詢剖析器 和 標準查詢剖析器 都支援函數查詢。
函數查詢使用函數。函數可以是常數(數值或字串文字)、欄位、另一個函數或參數取代引數。您可以使用這些函數來修改使用者結果的排名。這些可用於根據使用者的位置或其他一些計算來變更結果的排名。
使用函數查詢
函數必須表示為函數呼叫(例如,sum(a,b)
而不是簡單的 a+b
)。
在 Solr 查詢中有多種使用函數查詢的方式
-
透過期望函數引數的明確查詢剖析器,例如
func
或frange
。例如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)"
建議僅使用具有快速隨機存取的函數。
可用的函數
下表總結了可用於函數查詢的函數。
childfield(欄位) 函數
在透過 {!parent}
搜尋時,傳回其中一個相符子文件的給定欄位值。它只能在 sort
參數中使用。
語法範例
-
sort=childfield(name) asc
表示$q
作為第二個引數,因此它假設q={!parent ..}..
; -
sort=childfield(field,$bjq) asc
指的是單獨的參數bjq={!parent ..}..
; -
sort=childfield(field,{!parent of=…}…) desc
允許內嵌區塊聯結父查詢
def 函數
def
是 default (預設值) 的縮寫。傳回欄位 "field" 的值,如果該欄位不存在,則傳回指定的預設值。產生第一個 exists()==true
的值。
語法範例
-
def(rating,5)
:這個def()
函式會傳回評分,如果文件中沒有指定評分,則傳回 5。 -
def(myfield, 1.0):
等同於if(exists(myfield),myfield,1.0)
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
的名稱,也可以是常數向量。
如果指定了兩個欄位名稱,則它們的配置必須具有相同的 vectorDimensions
、vectorEncoding
和 similarityFunction
。如果指定了常數向量,則會使用第一個參數指定的欄位上配置的 vectorEncoding
來剖析該常數向量,且該常數向量的維度必須相同。
語法範例
-
vectorSimilarity(vectorField1, vectorField2)
:計算每個文件的向量欄位vectorField1
和vectorField2
之間設定的相似度。 -
vectorSimilarity(vectorField1, [1,2,3,4])
:計算每個文件的向量欄位vectorField1
和[1, 2, 3, 4]
之間設定的相似度。
只有遵循建議的欄位命名慣例的欄位名稱才能保證與此語法搭配使用。在函式查詢中使用時,需要 field("…") 語法的非典型欄位名稱,必須使用下面描述的 vectorSimilarity(…) 函式更複雜的 4 個參數變體語法。 |
vectorSimilarity(ENCODING, SIMILARITY_FUNCTION, vector1, vector2)
輸入向量元素編碼、相似度度量,加上兩個 ValueSource 實例(可以是 DenseVectorField
或常數向量),並計算兩個向量之間的相似度。
-
支援的編碼有:
BYTE
、FLOAT32
-
這用於剖析任何常數向量參數
-
-
支援的相似度有:
EUCLIDEAN
、COSINE
、DOT_PRODUCT
語法範例
-
vectorSimilarity(FLOAT32, COSINE, [1,2,3], [4,5,6])
:計算每個文件的[1, 2, 3]
和[4, 5, 6]
之間的餘弦相似度。 -
vectorSimilarity(FLOAT32, DOT_PRODUCT, vectorField1, vectorField2)
:計算每個文件的vectorField1
和vectorField2
中向量之間的點積相似度。 -
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 時,可以指定可選的第二個參數來選取多值欄位的 min
或 max
值。
對於欄位中沒有值的文件,會傳回 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
,其中 m
和 c
是常數,而 x
是任意函式。這等同於 sum(product(m,x),c)
,但效率更高,因為它是以單一函式實作的。
語法範例
-
linear(x,m,c)
-
linear(x,2,4)
:傳回2*x+4
map 函式
將輸入函式 x
的任何值(包含在 min
和 max
之間)對應到指定的 target
。參數 min
和 max
必須是常數。參數 target
和 default
可以是常數或函式。
如果 x
的值不在 min
和 max
之間,則會傳回 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)
:將0
到100
之間的任何值變更為1
,將所有其他值變更為-1
。 -
map(x,0,100,sum(x,599),docfreq(text,solr))
:將0
到100
之間的任何值變更為 x+599,將所有其他值變更為欄位 text 中詞彙 'solr' 的頻率。
-
max 函式
傳回多個巢狀函式或常數的最大數值,這些函式或常數會指定為引數:max(x,y,…)
。max
函式對於將另一個函式或欄位「限制」在某些指定的常數也是很有用的。
使用 field(myfield,max)
語法來選取單一多值欄位的最大值。
語法範例
-
max(myfield,myotherfield,0)
min 函式
傳回多個巢狀函式或常數的最小數值,這些函式或常數會指定為引數:min(x,y,…)
。min
函式對於使用常數為函式提供「上限」也是很有用的。
使用 field(myfield,min)
語法來選取單一多值欄位的最小值。
語法範例
-
min(myfield,myotherfield,0)
ms 函式
傳回引數之間的毫秒差異。日期相對於 Unix 或 POSIX 時間基準,1970 年 1 月 1 日午夜 UTC。
引數可以是 DatePointField
、TrieDateField
的名稱,也可以是基於常數日期或 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)
ord 函數
傳回在 Lucene 索引順序(按 Unicode 值依字典順序排序)中,索引欄位值在該欄位索引詞彙列表中的序數,從 1 開始。
換句話說,對於給定的欄位,所有值都按字典順序排序;然後此函數傳回特定值在該排序中的偏移量。該欄位每個文件最多只能有一個值(不能是多值)。如果文件中沒有該欄位的值,則傳回 0
。
ord() 取決於索引中的位置,並且在插入或刪除其他文件時可能會變更。 |
另請參閱下方的 rord
。
語法範例
-
ord(myIndexedField)
-
如果特定欄位 X 只有三個值("apple"、"banana"、"pear"),則對於包含 "apple" 的文件,
ord(X)
將為1
,對於包含 "banana" 的文件,則為2
,依此類推。
payload 函數
傳回從指定詞彙的解碼酬載計算出的浮點數值。
傳回值是使用解碼酬載的 min
、max
或 average
計算得出的。可以使用特殊的 first
函數來取代其他函數,以短路詞彙列舉並僅傳回第一個詞彙的解碼酬載。
指定的欄位必須具有浮點數或整數酬載編碼功能(透過 DelimitedPayloadTokenFilter
或 NumericPayloadTokenFilter
)。如果未找到詞彙的酬載,則傳回預設值。
-
payload(field_name,term)
:預設值為 0.0,使用average
函數。 -
payload(field_name,term,default_value)
:預設值可以是常數、欄位名稱或其他傳回浮點數的函數。使用average
函數。 -
payload(field_name,term,default_value,function)
:函數值可以是min
、max
、average
或first
。
語法範例
-
payload(payloaded_field_dpf,term,0.0,first)
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
是任意複雜的函數。
當 a
和 b
相等,且 x>=0
時,此函數的最大值為 1
,且會隨著 x
的增加而下降。同時增加 a
和 b
的值會導致整個函數移動到曲線的較平坦部分。當 x 為 rord(datefield)
時,這些屬性可以使此函數成為提升較新文件的理想函數。
語法範例
-
recip(myfield,m,a,b)
-
recip(rord
(creationDate), 1,1000,1000)
scale 函數
縮放函數 x
的值,使其落在指定的 minTarget
和 maxTarget
(含)之間。目前的實作會遍歷所有函數值以取得最小值和最大值,因此它可以選擇正確的比例。
目前的實作無法區分文件何時已刪除或文件沒有值。它在這些情況下使用 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)
strdist 函數
計算兩個字串之間的距離。使用 Lucene 拼字檢查程式 StringDistance
介面,並支援該套件中提供的所有實作,此外還允許應用程式透過 Solr 的資源載入功能插入自己的實作。strdist
接受 (string1, string2, 距離測量)。
距離測量的可能值為
-
jw: Jaro-Winkler
-
edit: Levenshtein 或編輯距離
-
ngram:如果指定,NGramDistance 也可以選擇性地傳入 ngram 大小。預設值為 2。
-
FQN:StringDistance 介面實作的完整限定類別名稱。必須具有無引數建構函式。
語法範例
-
strdist("SOLR",id,edit)
sum 函數
傳回以逗號分隔的清單中指定的多個值或函數的總和。add(…)
也可用作此函數的別名。
語法範例
-
sum(x,y,…)
-
sum(x,1)
-
sum(sqrt(x),log(y),z,0.5)
-
add(x,y)
sumtotaltermfreq 函數
傳回整個索引中欄位中所有詞彙的 totaltermfreq
值的總和(即,該欄位的索引符號數)。(別名 sumtotaltermfreq
為 sttf
。)
語法範例 如果 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
tf 函數
詞彙頻率;使用該欄位的 相似度,傳回給定詞彙的詞彙頻率因子。tf-idf
值與單字在文件中出現的次數成比例增加,但會被單字在文件中的頻率抵消,這有助於控制某些單字通常比其他單字更常見的事實。另請參閱 idf
。
語法範例
-
tf(text,'solr')
布林函數
以下函數是布林函數 – 它們傳回 true 或 false。它們主要用作 if
函數的第一個引數,並且其中一些可以組合。如果在其他地方使用,它將產生 '1' 或 '0'。
and 函數
當且僅當其所有運算元都評估為 true 時,才傳回 true 值。
語法範例
-
and(not(exists(popularity)),exists(price))
:對於在price
欄位中具有值,但在popularity
欄位中沒有值的任何文件,傳回true
。
xor 函數
邏輯互斥分離,或兩者之一但不同時成立。
語法範例
-
如果
field1
或field2
為 true,則xor(field1,field2)
傳回true
;如果兩者都為 true,則為 FALSE。
exists 函數
如果欄位的任何成員存在,則傳回 true
。
語法範例
-
exists(author)
:對於在 "author" 欄位中具有值的任何文件,傳回true
。 -
exists(query(price:5.00))
:如果 "price" 符合 "5.00",則傳回true
。
函數查詢範例
為了讓您更了解如何在 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>