函数查询

函数查询使您能够使用一个或多个数字字段的实际值生成相关性得分。

函数查询使用函数。函数可以是常量(数字或字符串文本)、字段、另一个函数或参数替换参数。您可以使用这些函数修改结果对用户显示的排名。这些函数可用于根据用户的地理位置或其他一些计算更改结果的排名。

使用函数查询

函数必须表示为函数调用(例如,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(field) 函数

通过 {!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,"-"))

"constant" 函数

指定浮点常量。

语法示例

  • 1.5

def 函数

def 是默认值的缩写。返回字段 "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 向量之间的相似性。获取输入向量元素编码、相似性度量以及两个 ValueSource 实例,并计算两个向量之间的相似性。

  • 支持的编码有:BYTEFLOAT32

  • 支持的相似性有:EUCLIDEANCOSINEDOT_PRODUCT

每个 ValueSource 必须是一个 knn 向量(字段或常量)。

语法示例

  • 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 时,可以指定一个可选的第二个参数来选择多值字段的 minmax 值。

对于字段中没有值的文档,将返回 0。

语法示例 这 3 个示例是等效的

  • myFloatFieldName

  • field(myFloatFieldName)

  • field("myFloatFieldName")

当你的字段名称不典型时,最后一种形式很方便

  • field("my complex float fieldName")

对于多值 docValues 字段

  • field(myMultiValuedFloatField,min)

  • field(myMultiValuedFloatField,max)

hsin 函数

Haversine 距离计算沿着球体行进时球体上两点之间的距离。值必须以弧度为单位。hsin 还接受一个布尔参数来指定函数是否应将其输出转换为弧度。

语法示例

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

idf 函数

逆文档频率;衡量术语在所有文档中是否常见或罕见。通过将文档总数除以包含该术语的文档数,然后取该商的对数来获得。另请参见tf

语法示例

  • idf(fieldName,'solr'):衡量术语'solr'fieldName中出现的频率的倒数。

if 函数

启用条件函数查询。在if(test,value1,value2)

  • test是逻辑值或返回逻辑值(TRUE 或 FALSE)的表达式的引用。

  • value1是当test产生 TRUE 时由函数返回的值。

  • value2是当test产生 FALSE 时由函数返回的值。

表达式可以是输出布尔值的任何函数,甚至可以是返回数字值的函数,在这种情况下,值 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的值,或者如果指定为第 5 个参数,则返回默认值。

语法示例

  • 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,并将所有其他值更改为术语“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(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'}):返回流行度和 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 作为要映射的最小值。在这些情况下,可以使用适当的 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: Levenstein 或编辑距离

  • 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 值的总和(即该字段的已索引词条数)。(将 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

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')

布尔函数

以下函数为布尔函数 - 它们返回真或假。它们主要用作 if 函数的第一个参数,其中一些可以组合。如果在其他地方使用,它将产生 '1' 或 '0'。

and 函数

当且仅当其所有操作数都计算为真时,返回真值。

语法示例

  • and(not(exists(popularity)),exists(price)):对于在 price 字段中有值但 popularity 字段中没有值的任何文档,返回 true

or 函数

逻辑析取。

语法示例

  • or(value1,value2): 如果 value1value2 为真,则为 true

xor 函数

逻辑异或,或一个或另一个,但不能同时存在。

语法示例

  • xor(field1,field2) 如果 field1field2 为真,则返回 true;如果两者都为真,则返回 FALSE。

not 函数

包装函数的逻辑否定值。

语法示例

  • not(exists(author)):仅当 exists(author) 为假时才为 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 中使用函数查询,假设一个索引存储了某些假设框的维度(以米为单位)x、y、z,这些框的任意名称存储在字段 boxname 中。假设我们要搜索名称匹配 findbox 的框,但根据框的体积进行排名。查询参数将是

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

此查询将根据体积对结果进行排名。为了获得计算出的体积,你需要请求 score,其中将包含结果体积

&fl=*, score

假设你还有一个字段,将框的重量存储为 weight。要按框的密度排序并在 score 中返回密度值,你可以提交以下查询

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

按函数排序

你可以按函数的输出对查询结果进行排序。例如,要按距离对结果进行排序,你可以输入

http://localhost: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>