Solr搜索介绍(Searching)

1. 概览

在Solr中运行一个搜索时,搜索查询(search query)由一个request handler处理。
一个request handler是一个Solr插件,定义了Solr处理请求时使用的逻辑。Solr支持各种请求处理器。

Search应用默认选择一个特定的request handler. 用户可以配置选择一个不同的request handler来覆盖默认的选择。

处理一个搜索查询,request handler调用一个query parser, 解析查询的短语和参数。不同的parser支持不同的语法。
Solr的默认解析器是Standard Query Parser, 或者说"lucene" query parser. 支持更精确搜索的查询语法。
Solr也包含DisMax query parser 和 Extended DisMax(eDisMax) query parser. 容错性更好。

一个query parser输入包括:
* 搜索字符串 --- 索引中的搜索terms
* 调整查询的参数,通过增加特定字串和字段的重要性,通过在terms之间应用布尔逻辑,或通过从结果排除内容等。
* 用控制查询返回形式的参数,如指定结果顺序或限制结果返回字段。

搜索参数可以指定一个filter query. 过滤查询将对整个索引进行并且缓存结果。Solr使用单独的filter缓存,不同的策略能提升搜索性能。

一个搜索查询可以要求在结果中特定terms被加亮(highlighted). Solr支持multi-term加亮。

搜索返回也可以配置为包含摘要(snippets).

Solr支持两中方式的结果分组:faceting 和 clustering.
Faceting 将搜索结果分成不同的分类(基于索引词). 每个分类有相关结果的数目。
Clustering 将搜索结果按相似度分组,相似度是在搜索时计算的,而不是索引时。用来发现结果中未知的共同性。

Solr也支持MoreLikeThis功能,使用户能提交一个新的查询,关注于之前一个query返回的特定terms. 可以利用faceting和clustering.

Solr组件response writer管理查询响应的最终表示。包含XML Response Writer 和 JSON Response Writer.

2. 快速搜索界面(Velocity Search UI)

Solr包含一个基于VelocityResponseWriter的样例搜索界面,演示若干特性,
如搜索(searching), 切面(faceting), 高亮(highlighting), 自动补全(autocomplete), 空间搜索(geospatial searching)等。

访问地址: http://localhost:8983/solr/collection_name/browse

3. 相关度(Relevance)

Relevance是搜索信息的用户对查询返回的满意度。

两个跟relevance相关的重要概念:
精确度(Precision): 返回的相关文档在返回结果中占有的百分比。
召回率(Recall):返回的相关文档占系统中所有相关结果的百分比。

https://lucidworks.com/blog/2009/09/02/debugging-search-application-relevance-issues/

4. 查询语法和解析 (Query Syntax and Parsing)

query parser插件都是QParserPlugin的子类。如果你有定制解析的需要,可以扩展这个类来创建自己的查询parser.
有一些查询参数通用于所有Solr解析器,这些在通用查询参数(Common Query Parameters)中讨论。

4.1 通用查询参数(Common Query Parameters)

- defType    
指定用于处理主查询参数(q)的解析器(query parser)
defType=dismax, 默认defType=lucene

- sort       
排序字段:multiValued="false"并且docValues="true"或indexed="true"(non-tokenized, single term)
列:
score desc (默认)
price asc
inStock desc, price asc

- start      默认0

- rows       默认10

- fq         过滤查询(filter query)
fq=popularity:[10 TO *]&fq=section:0
fq=+popularity:[10 TO *] +section:0
每个filter query有各自独立的cache, 因此,经常一起出现的语句放在同一个fq参数中;不经常一起出现的放在各自的fq参数中。
URL中的特殊字符需要编码

- fl         
Field List返回的字段列表(stored="true"或docValues="true")
例:
id name price
id,name,price
id name, price
id score

* score
*,dv_field_name
函数值: fl=id,title,product(price,popularity)
Document Transformers: fl=id,title,[explain]
字段别名:fl=id,sales_price:price,secret_sauce:prod(price,popularity),why_score:[explainstyle=nl]

- debug      
debug=query     只返回query相关信息
debug=timing    返回时间信息
debug=results   解释("explain")文档打分信息, 可指定debug.explain.structured=true
debug=all       所有信息(debug=true)

- explainOther    
指定一个Lucene查询来定位一个文档集合,返回匹配上此查询的"explain info".

- timeAllowed     
允许的查询时间,超时则返回部分结果。

- omitHeader      
true 忽略返回的头部信息;默认false

- cache=false
fq={!frange l=10 u=100}mul(popularity,price)
fq={!frange l=10 u=100 cache=false}mul(popularity,price)
fq={!frange l=10 u=100 cache=false cost=100}mul(popularity,price)

- wt              
指定Response Writer

- logParamsList   
默认记录所有参数;logParamsList=q,fq

4.2 标准查询解析器(The Standard Query Parser)

也称为"lucene"解析器。

(1) 参数

除了通用参数,Faceting参数,Highlighting参数和MoreLikeThis参数外,标准解析器还支持下列参数:
q      使用标准查询语法定义query, 必须
q.op   指定默认操作:AND或OR
df     指定默认搜索字段

(2) 响应

XML

(3) 指定Terms
有两种类型的terms:单独terms 和 短语(phrases)

- 通配符搜索(Wildcard Searches)
单字符    ?    te?t
多字符    *    tes*, te*t, *est

- 模糊搜索 (Fuzzy Searches)
Solr基于Damerau-Levenshtein距离或编辑距离算法支持模糊搜索。
例:
roam~      查询拼写相似的词:如 roams,foam, roam
roam~1     编辑距离为1

- 邻近搜索(Proximity Searches)
"jakarta apache"~10        查询apache和jakarta两个词相距10个词(移动10次)以内的文档。

- 范围搜索(Range Searches)
mod_date:[20020101 TO 20030101]
title:{Aida TO Carmen}

- 使用^来Boosting Term
jakarta^4 apache
"jakarta apache"^4 "Apache Lucene"

- 使用^=来设定常量score
(description:blue OR color:blue)^=1.0 text:shoes

(4) 在查询中指定字段
title:"The Right Way" AND text:go
title:"Do it right" AND go              text是默认字段

(5) 布尔操作
AND (&&)
NOT (!)
OR  (||)
+
-    类似NOT

例:
"jakarta apache" jakarta
"jakarta apache" OR jakarta
"jakarta apache" AND "Apache Lucene"
"jakarta apache" && "Apache Lucene"
"jakarta apache" NOT "Apache Lucene"
"jakarta apache" ! "Apache Lucene"
+jakarta lucene
"jakarta apache" -"Apache Lucene"

跳过特殊字符:
+ - && || ! ( ) { } [ ] ^ " ~ * ? : /

(1+1):2  转义: \(1\+1\)\:2

(6) 子查询分组

(jakarta OR apache) AND website
title:(+return +"pink panther")

(7) 注释
"jakarta apache" /* this is a comment in the middle of a normal query string */ OR jakarta

(8) Solr标准查询解析器和Lucene查询解析器的区别

- *号可以用于指定范围查询的两端。
  field:[* TO 100], field:[100 TO *], field:[* TO *]
- 允许使用单纯的非查询(只作为顶层查询)。
  -inStock:false, field:[* TO *]
- 如果函数查询包含括号,需要用引号括起来。
  _val_:"recip(rord(myfield),1,2,3)"
- 支持任意parser类型作为嵌套语句。
  inStock:true OR {!dismax qf='name manu' v='ipod'}
- 支持使用filter(...)语法来表明某些子查询使用filter cache.
  q=features:songs OR filter(inStock:true)
  q=+manu:Apple +filter(inStock:true)
  q=+manu:Apple & fq=inStock:true
- 范围查询,前缀查询,通配符查询都是常量打分(全部一样的分数)。没有term数目的限制。

查询TrieDateField应该使用适当的语法结构:
timestamp:[* TO NOW]
createdate:[1976-03-06T23:59:59.999Z TO *]
createdate:[1995-12-31T23:59:59.999Z TO 2007-03-06T00:00:00Z]
pubdate:[NOW-1YEAR/DAY TO NOW/DAY+1DAY]
createdate:[1976-03-06T23:59:59.999Z TO 1976-03-06T23:59:59.999Z+1YEAR]
createdate:[1976-03-06T23:59:59.999Z/YEAR TO 1976-03-06T23:59:59.999Z]

4.3 DisMax 查询解析器

DisMax query parser设计用于处理用户输入的简单phrases, 和一个搜索词以不同权重搜索不同字段。
它接受简单的语法,并且很少产生错误信息(对语法要求没那么严格)。

DisMax 支持 Lucene QueryParser语法的一个子集。
引号用于分组,+/-用于指定必要和可选子查询。其他特殊字符(除AND和OR)都被忽略,以简化用户体验。

DisMax 代表 Maximum Disjunction.

参数:
q
q.alt   当q未指定时,调用标准解析器并指定输入字符串
qf      指定查询字段。未指定则使用df.   qf="fieldOne^2.3 fieldTwo fieldThree^0.4"
mm      Minimum "Should" Match: 最少应匹配的子查询数。 3,-2,75%,-25%,3<90%, 2<-25% 9<-3
pf      Phrase Fields: boost terms邻近出现的文档
ps      Phrase Slop: 指定短语匹配时term之间可分隔的位置
qs      Query Phrase Slop: 指定短语匹配时term之间可分隔的位置
tie     Tie Breaker: 浮点数 < 1
bq      Boost Query
bf      Boost Function


4.4 Extended DisMax 查询解析器

改进的DisMax。除了DisMax参数,还支持:
- 支持完整Lucene查询语法
- 支持AND, OR, NOT, -, +
- 视and和or 为 AND和OR
- 'magic field': _val_解析为函数;_query_解析为嵌套。
- 改进的邻近boosting
- 改进的停用词处理
- 改进的boost function: 作为乘数而非加数
- 支持单纯的非查询:+foo (-foo)

- 指定终端用户可以搜哪些字段,并拒绝字段查询。

4.5 函数查询(Function Queries)

函数查询使你能使用一个或多个数值字段生成一个相关度分数。

- 使用函数查询

函数必须表示为函数调用,只推荐使用能快速进行存取的函数。

在Solr查询中,有几种方式可以使用函数(functions):
* 通过QParser显示的传递function参数,如func或frange.
  q={!func}div(popularity,price)&fq={!frange l=1000}customer_ratings
  
* 在Sort表达式中。
  sort=div(popularity,price) desc, score desc
  
* 将function结果作为伪字段添加到查询结果文档中。
  &fl=sum(x, y),id,a,b,c,score
  
* 使用用于指定函数的参数,如EDisMax的boost参数,或DisMax查询的bf(boost function)参数.
  q=dismax&bf="ord(popularity)^0.5 recip(rord(price),1,1000,1000)^0.3"
  
* 在lucene QParser中通过_val_关键字使用内联函数。

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

- 可用的函数

abs    绝对值
and    true/false, 例and(not(exists(popularity)),exists(price)) 
"constant"    浮点数
def    返回字段值, def(myfield, 1.0): 等价于 if(exists(myfield),myfield,1.0)
div    div(1,y)
dist   返回两个n维向量(点)间的距离;dist(2, x, y, 0, 0): 计算(0,0)和(x,y)之间的欧式距离; dist(1, x, y, 0, 0)计算Manhattan距离。
docfreq(field, val)    返回字段包含val的文档数;docfreq(text,'solr')
exists   返回true如果字段存在;exists(author);exists(query(price:5.00))
field    返回字段的数值docValues或索引值。
           等价的三种形式:myFloatFieldName;field(myFloatFieldName);field("myFloatFieldName")
  对multivalued docValues字段:field(myMultiValuedFloatField,min);field(myMultiValuedFloatField,max)
sphere   Haversine距离计算两个点的球面距离,值必须是弧度,boolean参数表示是否需要将输出转化为弧度。hsin(2, true, x, y, 0, 0)
idf      反文档频率;idf(fieldName,'solr')  
if       条件查询函数:if(test,value1,value2); if(termfreq(cat,'electronics'),popularity,42)
linear   实现m*x+c,m和c是常量,等价于sum(product(m,x),c)但更高效;  linear(x,m,c)
log      10为底数的log
map      map(x,min,max,target), min和max之间的值转为target
         map(x,min,max,target,default), min和max之间的值转为target, 其他为default
max      选择最大值;max(myfield,myotherfield,0)
min      返回最小值;min(myfield,myotherfield,0)
ms       返回参数毫秒数;ms()等价ms(NOW); ms(a); ms(a,b) 为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", 这是索引时boost和长度规范化因子的product(点积?)  
maxdoc    返回索引文档数,包括被标记为删除但还未被purged
numdocs   返回索引文档数,不包括被标记为删除但还未被purged
not       not(exists(author)): true/false
or        or(value1,value2): true/false
ord       返回字段索引值在Lucene索引顺序中的序号(ordinal)
rord      返回ord的逆序
pow       幂
product   点积(或mul(...)); product(x,y,...)
query     返回给定子查询的分数。query(subquery,default)  
          列 product(popularity, query({!dismax v='solr rocks'}) 等价于 q=product(popularity,query($qq))&qq={!dismax}solr rocks
recip     倒数(reciprocal); recip(x,m,a,b) = a/(m*x+b) 
            当x为rord(datefield)时,这是一个理想的函数用于boosting更多最新的文档。
scale     将x值按比例放入[minTarget, maxTarget]范围内。 scale(x,1,2)
sqedist   欧式距离平方。sqedist(x_td, y_td, 0, 0)
sqrt      平方根
strdist   字符串距离,使用Lucene的StringDistance接口。 (string1, string2, distance measure); strdist("SOLR",id,edit)
             distance measure: jw(Jaro-Winkler), edit(Levenstein或编辑距离), ngram(默认2)
sub        sub(x,y) = x - y
sum        求和(或add(...)); 
sumtotaltermfreq    或sttf, 返回字段索引中所有terms的总频次。
termfreq   返回文档中term出现的次数。 termfreq(text, 'memory')
tf         返回指定字段在Similarity中使用的tf因子。  termfreq(text, 'solr')
top        top(query)使查询从整个索引获取数据。如一个segment中的值顺序与在整个索引中的顺序不一样。ord()和rord()隐身的使用top(); 即ord()=top(ord())
totaltermfreq   或ttf,返回term在字段中的频次。 ttf(text, 'memory')
xor             异或

例子:
根据box体积排序: q=boxname:findbox _val_:"product(x,y,z)"   
根据box密度排序: q=boxname:findbox _val_:"div(weight,product(x,y,z))&fl=boxname x y z weight score
按距离排序:  q=*:*&sort=dist(2, point1, point2) desc
返回伪字段: &fl=id,sum(x, y),score

4.6 查询中的本地(自定义)参数 (Local Parameters)

基本语法:
* 以{!开始
* 插入以空格分隔的key=value对
* 以}结束

Value可以由单引号,双引号引用,反斜杠可转义(escaping)字符。

q={!q.op=AND df=title}solr rocks
q={!dismax qf=myfield}solr rocks  等价于  q={!type=dismax qf=myfield}solr rocks  # 隐式name为"type"  
fq={!df=summary}solr rocks  等价于  fq={!type=lucene df=summary}solr rocks
q={!dismax qf=myfield}solr rocks  等价于  q={!type=dismax qf=myfield v='solr rocks'} # 'v' key
q={!dismax qf=myfield}solr rocks  等价于  q={!type=dismax qf=myfield v=$qq}&qq=solr rocks

4.7 其他Parsers

- Block Join Query Parsers
可以搜索被索引为嵌入形式文档的相关内容。

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

q={!child of="content_type:parentDocument"}title:lucene
q={!parent which="content_type:parentDocument"}comments:SolrCloud

打分:
local parameter: score=avg,max,min,total(sum),none

- Boost Query Parser

BoostQParser扩展自QParserPlugin, 并从输入(参数)创建一个boosted查询。 'b'参数是用于boost的函数查询。
{!boost b=log(popularity)}foo
{!boost b=recip(ms(NOW,mydatefield),3.16e-11,1,1)}foo

- Collapsing Query Parser
CollapsingQParser是一个后过滤器,当结果分组太多时,将每个分组缩减为一个文档。(faceting,highlighting)

- Complex Phrase Query Parser
ComplexPhraseQParser支持通配符(wildcards), ORs.., 利用Span系列查询。
参数
inOrder: 强制按顺序匹配
df: 默认搜索字段

{!complexphrase inOrder=true}name:"Jo* Smith" 
{!complexphrase inOrder=false}name:"(john jon jonathan~) peters*"
+_query_:"{!complexphrase inOrder=true}manu:\"a* c*\"" +_query_:"{!complexphrase inOrder=false df=name}\"bla* pla*\""

限制:
过短前缀(如a*),会生成一个巨大的OR(SpanOR)语句,并可能返回大量低质量的结果。
solrconfig.xml: <maxBooleanClauses>4096</maxBooleanClauses>

停用词:
此Parser不推荐使用stopword.

- Field Query Parser
{!field f=myfield}Foo Bar 等价于 . myfield:"Foo Bar"

- Function Query Parser
{!func}log(foo)
其他方法参考:Function Queries

- Function Range Query Parser

参数:
l, lower bound
u, upper bound
incl, 包含lower边界,默认true
incu, 包含upper边界,默认false

{!frange l=1000 u=50000}myfield
fq={!frange l=0 u=2.2} sum(user_ranking,editor_ranking)

- Join Query Parser (关联查询)

可以使用Join操作normalizing文档间的关联。这与关系数据库的join概念不同,因为没有真正被join的信息。可以类比于SQL的"inner query".
select * from core
where to in (
  select from from core
  where field=value;
)

例:
{!join from=manu_id_s to=id}ipod
q = {!join from=id to=manu_id_s}compName_s:Belkin&fq = price:[* TO 12]

join操基于term, "from"和"to"字段必须是兼容字段类型。

打分:
local parameter: score=avg,max,min,total(sum),none

跨Collection的Join:
可以通过fromIndex参数指定另一个core或collection的from字段。[查看更多详情]

fq={!join from=id fromIndex=movie_directors to=director_id}has_oscar:true

- Lucene Query Parser
{!lucene q.op=AND df=text}myfield:foo +bar -baz

- Max Score Query Parser
MaxScoreQParser扩展自LuceneQParser, 但是返回语句中的最大分数。非boolean查询,使用LuceneQParser.
{!maxscore tie=0.01}C OR (D AND E)

- More Like This Query Parser
MLTQParser能获取给定文档的相似文档。使用Lucene的MoreLikeThis逻辑,也适用于SolrCloud模式。返回的结果不包含自身。

参数:
qf       用于相似度的字段
mintf    最小TF值
mindf    最小DF值
maxdf    最大DF值
maxwl    最小word长度
maxqt    是生成的查询中的最多query term数
maxntp   没有termVector时,每个field最多解析tokens数
boost    true/false, 是否基于term相关度做boosting.

例:
{!mlt qf=name mintf=2 mindf=3}1   # (unique) id=1 的相似文档

- Nested Query Parser (嵌套查询)
solrconfig.xml中定义:
<lst name="defaults">
  <str name="q1">{!lucene}inStock:true</str>
</lst>

{!query defType=func v=$q1}

- Old Lucene Query Parser
{!lucenePlusSort} myfield:foo +bar -baz;price asc

- Prefix Query Parser
{!prefix f=myfield}foo  等价于  myfield:foo*

- Raw Query Parser (原生查询)
RawQParser创建一个term query, 而不会分析输入(进行切词等).
{!raw f=myfield}Foo Bar  等价于  TermQuery(Term("myfield","Foo Bar"))
faceting推荐用TermQParserPlugin

- Re-Ranking Query Parser
详见相关小节

- Simple Query Parser

- Spatial Query Parsers (空间查询)

Solr有两个空间QParsers: geofilt和bbox. 
但是有其他方式进行空间搜索:使用frange parser和距离函数;使用标准(lucene)parser和范围语法选择矩形, 或RPT和BBoxFiled.

- Surround Query Parser
支持邻近搜索。w顺序有关,n顺序无关,最小距离1,最大距离99.

{!surround} 3w(foo, bar)  # 查找foo和bar之间不超过3个term距离的文档(它们之间最多两个term).

- Switch Query Parser (条件查询)

以下查询结果都是XXX:
{!switch case.foo=XXX case.bar=zzz case.yak=qqq}foo
{!switch case.foo=qqq case.bar=XXX case.yak=zzz} bar // extra whitespace is trimmed
{!switch case.foo=qqq case.bar=zzz default=XXX}asdf // fallback to the default
{!switch case=XXX case.bar=zzz case.yak=qqq} // blank input uses 'case'

一个特殊用法是在配置中指定appends fq参数:
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="in_stock">yes</str>
<str name="shipping">any</str>
</lst>
<lst name="appends">
<str name="fq">{!switch case.all='*:*'
case.yes='inStock:true'
case.no='inStock:false'
v=$in_stock}</str>
<str name="fq">{!switch case.any='*:*'
case.free='shipping_cost:0.0'
v=$shipping}</str>
</lst>
</requestHandler>

- Term Query Parser
参数:
f

例:
{!term f=weight}1.5

- Terms Query Parser
类似于Term Query,但支持多个Terms.

参数:
f
separator    默认","
method       termsFilter(默认), booleanQuery, automaton 或 docValuesTermsFilter

例:
{!terms f=tags}software,apache,solr,lucene
{!terms f=categoryId method=booleanQuery separator=" "}8 6 7 5309

- XML Query Parser

支持从XML创建查询[略]


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值