在solr的document文档定义中(schema.xml),需要对每个字段进行定义indexed, stored,其中表示的含义为:
字段名称 | 字段含义 | |
indexed |
如果该字段是要做查询的,需要将其设置为indexed,进行索引,以便能够根据该字段进行查询。
但是与具体分词手段无关,如果涉及到如果分词,需要使用type属性
|
|
stored | 在solr查询结果中能够正常返回,如果一个字段stored=false,则查询结果不会包括该字段。 |
而只有indexed的字段可以用于查询,虽然solr中有sort字段可以进行排序,这一般用于精确匹配的查询,例如按照分类/品牌进行搜索得到结果。如果用户采用关键词的方式进行模糊匹配,此时使用sort根据某个字段进行排序会显得不合时宜,无法帮助用户搜索到他想要的结果(更多是被sort所控制,这就好比百度的竞价排名系统)。
根据查询打分的相关文档可以看出,Solr中采用了最基本的向量空间模型:
其中存在的索引文件.tvx, tvd, tvf存储了term vector相关信息,我们学习如何使用term vector来反映相似性程度。在向量空间模型中,夹角越小,说明相似程度越大,可以用cos余弦函数定理来计算。
相似值计算公式:t=term, d=document, q=query, f=field
- tf(t in d ) 表示该term 在 这个文档里出现的频率(即出现了几次)。
- idf(t) 表示 出现该term的文档个数。
- t.getBoost() 查询语句中每个词的权重,可以在查询中设定某个词更加重要。
- norm(t,d) 标准化因子d.getBoost() • lengthNorm(f) • f.getBoost() ,它包括三个参数:
- Document boost:此值越大,说明此文档越重要。
- Field boost:此域越大,说明此域越重要。
- lengthNorm(field) = (1.0 / Math.sqrt(numTerms)):一个域中包含的Term总数越多,也即文档越长,此值越小,文档越短,此值越大。
- coord(q,d):一次搜索可能包含多个搜索词,而一篇文档中也可能包含多个搜索词,此项表示,当一篇文档中包含的搜索词越多,则此文档则打分越高 ,numTermsInDocumentFromQuery / numTermsInQuery
- queryNorm(q):计算每个查询条目的方差和,此值并不影响排序,而仅仅使得不同的query之间的分数可以比较。
我们当前环境的/select相关配置:
<!-- SearchHandler --> <requestHandler name="/select" class="com.zp.solr.handler.component.ZpSearchHandler"> <lst name="defaults"> <str name="defType">edismax</str> <str name="echoParams">explicit</str> <str name="wt">json</str> <str name="indent">true</str> <str name="df">text</str> <str name="bf"> map(psfixstock,0,0,0,100) </str> </lst> <shardHandlerFactory class="HttpShardHandlerFactory"> <int name="maxConnectionsPerHost">1000</int> <int name="corePoolSize">50</int> </shardHandlerFactory> </requestHandler> <!-- A request handler that returns indented JSON by default --> <requestHandler name="/query" class="solr.SearchHandler"> <lst name="defaults"> <str name="echoParams">explicit</str> <str name="wt">json</str> <str name="indent">true</str> <str name="df">text</str> </lst> </requestHandler>
可以看出当前使用了edismax方式,默认查询字段df为text,boost function已经被设置,但存在较大问题:搜索的排序严重与货物的库存数量相关,这肯定会导致用户无法查询出其想要的最精确的结果(即便是无库存,用户也可能希望能够返回正确的商品,而不是有库存的不相关商品)。Solr查询中的常用参数列表:
参数 | 含义 | |
df | default fields,默认查询字段 | |
wt | writer type,指定查询输出结构格式,默认xml | |
defType | 设置查询解析器名称 | |
bf | boost function,可接受多个函数查询,用空格隔开 | |
qf | query fields,指定索引中查询字段,如果没有指定,默认使用df | |
q | 查询字符串,必输项 | |
q.op | 默认查询连接符,AND OR | |
sort | 排序,sort=<field_name>+<desc|asc>,... | |
start | 分页定义结果起始记录数,默认为0 | |
rows | 分页定义结果每页返回记录数,默认为10 | |
fq | filter query,可充分利用filter query cache,提高检索性能。在q查询符合结果中同时是fq查询符合的 | |
fl | field list,指定返回结果字段,以空格或逗号分隔 | |
timeAllowed | 设置查询超时时间 | |
bq | boost query,指定一个单词或短语提升查询权重 | |
mm | Minimum Should Match,指定查询中必须匹配的最小规则数,如果没有在查询中或在solrconfig.xml文件中指定mm参数值,q.op参数的有效性将会受到影响。如果q.op是AND,则mm=100%,如果q.op是OR,则mm=1(100%表示全部匹配,1表示只要有一个匹配即可)。如果用户想修改这些行为,可以在solrconfig.xml文件中定义mm参数 |
Solr 支持多种查询解析,给搜索引擎开发人员提供灵活的查询解析。Solr 中主要包含这几个查询解析器:标准查询解析器、DisMax 查询解析器,扩展 DisMax 查询解析器(eDisMax)。
在solr查询时,使用debugQuery可以打印出其打分的详细信息以便我们能够正确的分析:
"1046888": " 26.279617 = sum of: 0.9810601 = sum of: 0.1401725 = weight(text:女士 in 431) [DefaultSimilarity], result of: 0.1401725 = score(doc=431,freq=2.0), product of: 0.3656968 = queryWeight, product of: 1.4455243 = idf(docFreq=37139, maxDocs=57987) 0.25298557 = queryNorm 0.3833025 = fieldWeight in 431, product of: 1.4142135 = tf(freq=2.0), with freq of: 2.0 = termFreq=2.0 1.4455243 = idf(docFreq=37139, maxDocs=57987) 0.1875 = fieldNorm(doc=431) 0.8408876 = weight(text:手提包 in 431) [DefaultSimilarity], result of: 0.8408876 = score(doc=431,freq=2.0), product of: 0.89569205 = queryWeight, product of: 3.5404868 = idf(docFreq=4570, maxDocs=57987) 0.25298557 = queryNorm 0.9388133 = fieldWeight in 431, product of: 1.4142135 = tf(freq=2.0), with freq of: 2.0 = termFreq=2.0 3.5404868 = idf(docFreq=4570, maxDocs=57987) 0.1875 = fieldNorm(doc=431) 25.298557 = FunctionQuery(map(int(psfixstock),0.0,0.0,const(0))), product of: 100.0 = map(int(psfixstock)=1,min=0.0,max=0.0,target=const(0)) 1.0 = boost 0.25298557 = queryNorm ",
女士手提包,搜索词拆分成两个词元:“女士” “手提包”,q.op默认为OR(通过设置mm的值可以影响该属性),
idf为出现的频率,单独搜索“女士”总条目数37139,单独搜索“手提包”总条目数4570,出现频次越多就越不重要,idf的计算公式:
idf(t) = 1 + log (numDocs / (docFreq +1))
termFreq=2.0,tf的计算公式,2的1/2次方,得出1.414:
tf(t in d) = numTermOccurrencesInDocument 1/2
fieldNorm取决于匹配的文档field总数,大概在29个左右(由于查询中并没有设置boost),计算公式:
lengthNorm(field) = (1.0 / Math.sqrt(numTerms))
queryNorm,用来计算每个查询条目的方差和,使得不同的query之间的分数可以进行比较:
写道
queryNorm(q) = 1 / (sumOfSquaredWeights )
sumOfSquaredWeights = q.getBoost()2 • ∑ ( idf(t) • t.getBoost() )2
sumOfSquaredWeights = q.getBoost()2 • ∑ ( idf(t) • t.getBoost() )2
Solr Copy Field对打分的影响
如果使用了solr中的copyfield,会对打分造成什么影响?copyfield,solr允许将不同的字段copy到一个字段中,搜索只需要搜索拷贝字段即可,当然这样会造成内容中包含非常多的搜索词。
根据在StackOverflow上的回答,如果要设置各自字段的boost,就不能使用统一的copyfield,或者将copyfield进行分组:
当前我们设置的默认df(default field)为<str name="df">text</str>,整个字段,当前我们可以通过更改qf的方式来做自定义boost,
SearchText, SearchText2^3, SearchText3^10, SearchText4^100
另一种说法,在solr中支持的多值域(multiValued)其实也就是copyfield,同一个field对应多个value。当一个文档中出现同名的多值域时,倒排索引和项向量都会在逻辑上将这些词的词汇单元附加进去。当对多值域进行存储的时候,它们在文档中的存储顺序是分离的,当在搜索期间对文档进行检索时,会发现多个field实例,最后该field的boost如何计算?使用每一个值域的boost相乘。
使用Query Field
我们设置query field,将下面的三个条件作为筛选条件,并设置其boost权重:
<str name="qf">brand_name^0.9 category_name^0.8 product_name^2.0</str>
此时我们查询 “胸饰”,从打开debugQuery,可以看到其中的详细评分:
"debug": { "rawquerystring": "胸饰", "querystring": "胸饰", "parsedquery": "(+DisjunctionMaxQuery((brand_name:胸饰^0.9 | category_name:胸饰^0.8 | product_name:胸饰^2.0)) FunctionQuery(map(int(psfixstock),0.0,0.0,const(0),const(100))))/no_coord", "parsedquery_toString": "+(brand_name:胸饰^0.9 | category_name:胸饰^0.8 | product_name:胸饰^2.0) map(int(psfixstock),0.0,0.0,const(0),const(100))",
我们可以定义多个 requestHandler,用来专门处理多种类型,例如模糊查询,根据商品id定位商品,后端的内部查询,将它们分开这样就可以完成不同的查询了。
相关推荐
首先,我们需要了解Solr的评分(Score)机制。Solr的默认评分是基于TF-IDF(词频-逆文档频率)算法的,它会根据查询词在文档中的出现频率和在整个索引中的普遍程度来计算相关性。然而,这种默认设置可能并不完全符合...
首先,让我们理解Solr的默认评分机制。Solr基于TF-IDF(词频-逆文档频率)算法来计算文档与查询的匹配度,得分越高表示匹配度越强。TF-IDF考虑了词在文档中的出现频率(Term Frequency, TF)和在整个文档集合中的...
首先,理解Solr的Schema是至关重要的。Schema是Solr的核心配置文件,名为`schema.xml`,它定义了索引中的字段类型(Field Types)和字段(Fields),以及搜索和排序的规则。在Schema中,每个字段都有其特定的数据...
在 Solr 中,文档得分是一个用来描述查询语句和文档之间匹配程度的变量。如果你希望通过干预 Lucene 查询来改变查询结果的排序,你就需要对 Lucene 的得分计算有所理解。 Lucene 的得分计算公式考虑了多个因素,...
1. **索引**:Solr 的核心是其索引机制,它将文档内容转换为可搜索的结构,如倒排索引,使得搜索操作可以快速高效地进行。 2. **Core**:Solr 的基本工作单元是 Core,每个 Core 都包含独立的配置和数据。一个 Solr ...
Nutch 源码的分析和理解对于想要深入研究搜索引擎工作原理、网页抓取技术和大数据处理的开发者来说至关重要。 在`apache-nutch-2.2.1`这个压缩包中,你将找到以下关键组成部分: 1. **源代码结构**:Nutch 的源...
这个离线版的Lucene 5.4.1官方文档提供了关于该版本的详细信息,包括API参考、指南和示例,帮助开发者更好地理解和使用Lucene的功能。 在Lucene 5.4.1中,主要包含了以下核心知识点: 1. **索引构建**: - **...
- **分布式搜索**:学习 `Solr` 或 `Elasticsearch`,它们基于 Lucene 提供了更高级别的服务,支持分布式索引和搜索。 - **性能调优**:研究如何通过优化缓存、调整内存分配等方式提升 Lucene 的性能。 - **近实时...
这个项目的重点在于提升对Lucene高级特性和优化技巧的理解。 首先,我们要了解Lucene的核心概念。索引是Lucene的核心,它是对数据的一种结构化表示,用于快速查找文档。在这个阶段,我们可能涉及到分词器...
**Lucene:基于Java的全文检索引擎简介** Lucene是一个高度可扩展的、高性能的全文检索库,由Apache软件基金会开发并维护。...通过深入理解其核心原理和最佳实践,开发者可以构建出高效、定制化的搜索引擎解决方案。
Lucene提供了高效的索引和搜索机制,使得开发者能够快速实现对大量文本数据的全文搜索。 ### 一、Lucene的架构 1. **索引过程**:Lucene的索引过程主要分为分析(Analyzer)、文档添加(Document)、段创建...
Lucene的搜索结果排序基于一个名为评分(Score)的机制。评分是根据查询词在文档中的出现频率、位置等因素计算得出的,高评分意味着文档与查询更匹配。开发者还可以通过定制Similarity类来调整评分算法,以满足特定...
**Lucene核心技术详解** Lucene是一个高性能、全文检索库,由Apache软件基金会开发并维护,是Java编写的一个开源搜索引擎框架...在第二天的资料和代码中,你可以进一步学习和实践这些知识,加深对Lucene的理解和运用。
《Lucene高级搜索进阶项目_02》 在深入探讨Lucene的高级搜索进阶项目之前,我们先来理解一下Lucene的核心概念。...通过不断学习和实践,你可以成为一个熟练的Lucene开发者,为各种应用场景构建强大的全文搜索引擎。
**全文检索Lucene** Lucene是Apache软件基金会的开源项目,它是一个高性能、...在深入学习Lucene的过程中,阅读《全文检索Lucene》这本书将是十分有益的,它将帮助你更好地理解和掌握Lucene的核心概念及其实现技巧。
《Lucene原理与代码分析完整版》是一份深入解析开源全文搜索引擎Lucene核心机制和技术细节的资料。Lucene是Apache软件基金会的一个项目,它为Java开发者提供了强大的文本搜索功能,被广泛应用于各种信息检索系统中。...
在实际应用中,常常结合Solr或Elasticsearch这样的分布式搜索引擎框架,以实现更高级的集群管理和分布式搜索功能。 综上所述,基于Lucene的自定义索引是一项涉及多方面技术的工作,包括分词器定制、字段配置、性能...
通过对Lucene源代码的研究,我们可以更深入地了解其内部机制,例如如何自定义Analyzer、构建Query对象、实现自定义的ScoreFunction等。这有助于我们优化索引性能、调整查询策略以及解决特定场景下的问题。 总的来...