搭建自己的搜索引擎:Apache Solr 7.x知识汇总

Coding Alan 5年前 (2019-08-14) 5298次浏览 0个评论 扫描二维码

为什么不是 Elastic?我也发出过同样的疑问,但技术本无高低,且我们的选择出发点永远是最适合自己的,而非最好的。对于项目而言我自然是优先选择团队小伙伴们原本就熟悉的。于是便有了这篇文章,实际上是很多融合了一本已出版英文原版书Mastering Apache Solr 7.x中的精华,其实我的选项并不多,因为大多数 Solr 相关的原书都是出版于2014-2015年,这是我所找到近年针对Solr近期版本的唯一的一本书。

官方文档:https://lucene.apache.org/solr/guide/7_7/

图示Solr 如何集成应用搭建自己的搜索引擎:Apache Solr 7.x知识汇总

安装

首先需确保安装了 java,通过如下命令进行验证

下载 Solr: http://lucene.apache.org/solr/downloads.html,如7.7.2:

默认配置两个节点,端口号分别为8983和7574

以上使用的是 cloud 模式,$SOLR_HOME/example下还包含其它配置集,有cloud, example-DIH, films和techproducts,均可通过 bin/solr -e xxx 来实现。

生产环境安装

从 MySQL导入数据

日志级别设置

后台Thread Dump中图标的状态:new, runnable, blocked, waiting, timed_waiting or terminated

schema 文件位置

主要目录

contrib: 包含高级的扩展如集群、语言监测、数据导入处理器等
dist:包含针对contrib模块的 jar文件、soleJ客户端文件和要部署到其它地方的 solr war 文件
docs:docs包含所有针对contrib模块的 HTML 文档,也包含一个简短的 Solr 教程
example:包含默认可用的配置集,不管我们选择哪种配置集,solr home 相应的变化
films:示例配置集,简单启动该配置集使用 solr -e start films
licenses:所有 Solr 依赖的证书文件

字段类型

通用属性

属性描述
namefieldType的名称
class用于索引和存储这一类型数据的class名称 that is used to index and store the data for this type.
positionIncrementGap针对多值字段。它用于指定多个值之间的距离。有助于避免本质上错误的词组匹配。
autoGeneratePhraseQueries用于TextField。如果值为true,Solr生成针对相邻词语的词组自动查询。如果值 false,那么词语应放在双引号中以避免被当作词组。
enableGraphQueries仅用于文本字段。仅在查询sow=false时可用。
DocValuesFormat用于定义自定义的DocValuesFormat
PostingsFormat帮助用于这个类型字段的自定义的PostingsFormat

字段默认属性

属性说明可用值默认值
indexed告知是否索引该字段。true/falsetrue
stored若值为true该字段的实际值可通过查询获取。true/falsetrue
sortMissingFirst和sortMissingLast如果不存在sort字段,它决定文档的位置。true/falsefalse
docValues如设为true这个字段的值放在面向列级的docValues结构。true/falsefalse
multiValued表示对于这个字段单个文档是否可以有多个值。true/falsefalse
omitNorms用于禁用字段长度归一化并节约内存。对所有主要的字段类型,默认值都是true。归一化仅对全文本字段才需要。true/false*
omitTermFreqAndPositions在为true时省略词语频次、位置和该字段提交的payload。对非文本字段默认值为true。true/false*
omitPositions类似于omitTermFreqAndPositions,但这时它保留有关词语频次的信息。true/false*
termVectors, termPositions, termOffsets, and termPayloads如果这些属性为true时Solr会为每个文档维护词语向量。这些向量可能包含针对每次词语出现的位置、偏移和payload信息。true/falsefalse
required告诉Solr不要接受尝试添加没有该字段的文档。true/falsefalse
useDocValuesAsStored这依赖于docValues的启用。如果将其设为 true 会进行启动并且会允许该字段在fl参数中匹配 * 时像存储字段一样返回true/falsetrue
large仅在stored="true"和multiValued="false"时才生效。为不在内存中产生缓存,它针对有大量值的字段。true/falsefalse

Solr 使用相似度来打分,使用的是BM25Similarity(Best Matching (BM)),可使用<similarity/>进行覆盖。

Solr 中的字段类型

  • BinaryField: 用于二进行数据。
  • BoolField: 用于布尔数据。可以为true或false。如果第一个字母是1,t或T,会被解析为true。所有其它值解释为false。
  • CollationField:用于校对排序的键,可用于地点相关的排序和范围查询。
  • CurrencyFieldType:用于货币和汇率。(CurrencyField已被淘汰)
  • DateRangeField:如名称的意思,它用于日期范围。
  • ExternalFileField::在需要从外部文件中拉取值时使用。
  • EnumFieldType:用于值的枚举集合。(EnumField已淘汰)
  • ICUCollationField:类似于CollationField,推荐用它替代CollationField。
  • LatLonPointSpatialField:用于纬度和经度坐标对多点的多个值。它能用按纬度, 经度的顺序指定,中间用逗号分隔。
  • PointType:在我们有单个值的多维点时使用,及我们需要对非纬度、非经度或处理稀有用例时排序空间数据时使用 。
  • PreAnalyzedField:在我们需要向Solr发送序列令牌流时使用时,来无需经过额外文本处理存储和索引。
  • RandomSortField:它不包含值,用于以随机顺序返回值。
  • SpatialRecursivePrefixTreeFieldType:它接受well-known text (WKT)格式的纬度、经度字符串。
  • StrField:这用小字段且不进行令牌化或分析。
  • TextField:用于多词或令牌。
  • DatePointField/DoublePointField/FloatPointField/IntPointField/LongPointField:这些类似相近的基于Trie的字段。唯一的不同在于它们使用基于维度点的数据结构且不要求任何精度配置。(TrieField, TrieDateField, TrieDoubleField, TrieFloatField, TrieIntField和TrieLongField等已淘汰)

UUIDField在传递NEW作为值时会生成一个新的UUID。在使用SolrCloud时推荐使用UUIDUpdateProcessorFactory来代替UUIDField生成UUID值,因为这样会让每个复制的每个文档都有唯一的UUID值。

Solr 使用DateTimeFormatter.ISO_INSTANT来进行格式化和解析:YYYY-MM-DDThh:mm:ssZ,其中 Z表示UTC。0000年之前的需添加 – 号,9999年之后的需添加+。-0002表示公元前3年。

可用的算式有NOW+4DAYS,NOW-6MONTHS,NOW/HOUR(当前时段的初始小时),可用的谓语:Intersects (默认)、 Contains、Within,如:fq={!field f=dateRange op=Contains}[1985 TO 1989]。

常用查询参数

参数行为默认值
defType选取查询解析器:defType=dismaxLucene(标准查询解析器)
sort对搜索结果以升序或降序排序。值可指定为asc或ASC 及 desc或DESC。排序支持数字或字母内容。Solr 支持克隆字段的排序.
例:salary asc: 根据salary排序 (由高到低)
name desc: 根据name排序 (z → a)
salary asc name desc: 首先对salary由高到低排序,然后再次对结果集按照name排序 (z → a).
desc
start指定结果开始展示的起点0
rows指定一次从完整结果集返回到客户端的最大文档数10
fq限制结果集通过对过滤查询的匹配的文档 (fq) 且不影响打分(score)
fl指定对每个匹配文档响应内返回的字段列表。这些字段可能过空格和逗号来指定。例如:
fl=id name salary: 仅返回id, name和salary
fl=id,name,salary: 仅返回id, name和salary
表示fl=*将返回所有字段。我们还可以通过和字段一起传递 score字段来返回每个文档字段的打分,例如:
fl=id score: 返回id字段和打分
fl=* score: 返回每个文档中的所有字段及每个字段的打分
*
debug返回具体值的调试信息。例如:
debug=query 将返回有关查询的信息
debug=timing将返回有关查询处理时间的调试信息
debug=results将返回有关打分结果的调试信息(explain)
debug=all或debug=true将返回请求的所有调试信息 
Not including debugging information
explainOther指定一个Lucene查询,将返回带有每个匹配该Lucene查询的每个文档的explain信息的调试信息,与原始查询相关(由q 参数所指定)。例如:
q=soccer&debug=true&explainOther=id:cricket
以上查询计算顶级匹配文档的打分 explain信息,并对比匹配id:cricket的文档的explain信息
blank
wt指定响应writer的格式。支持的格式有 json,  xml, xslt, javabin, geojson, python, php, phps, ruby, csv, velocity, smile和  xlsx。json
omitHeader告诉Solr从返回的结果中包含或排队头信息; omitHeader=true将从返回的结果中排除头信息。false
cache告诉Solr缓存所有查询和过滤器查询的结果。如果设为 false,它会禁用结果缓存。true

标准查询解析器

参数行为默认值
q指定使用标准查询语法的查询。这是一个针对任意请求的强制参数。
q.op指定针对查询表达式的默认运算符,它覆盖默认在 schema 中配置的运算符。可用值有AND或 OR。
df指定一个默认字段,它重载 schema 中的默认字段定义。
sow如果设置为true, 会在空格处进行分割。false

通配符搜索

通配符搜索类型特殊字符搜索示例
单个字符(匹配单个字符)?搜索字串 te?t 会匹配test 和 text。
多个字符 (匹配0或多个序列字符)*搜索字串 tes*会匹配 test, testing和 tester。这个通配符可用于词语的开头、中间或结尾。例如,字串te*t会匹配test 和 text,而*est会匹配pest 和 test。

模糊搜索: roam~会匹配roam, roams和 foam等词语。

邻近搜索: “soccer volleyball”~20对文档中soccer和volleyball间隔20个词以内会被匹配

范围搜索: price:[1000 TO 50000],包含使用[和],不包含使用{和},如price:[5 TO 20}

布尔运算符

运算符符号描述
AND&&要求两个词语都匹配。例如我们搜索包含soccer和volleyball的文档:
"soccer" AND "volleyball"
"soccer" && "volleyball"
NOT!要求不出现紧接着的词语。例如,我们搜索包含soccer但不包含volleyball的文档:
"soccer" NOT "volleyball"
"soccer" ! "volleyball"
OR||要求匹配其中一个词语。这是默认的连接运行符,例如,搜索包含soccer 或 volleyball的文档:
"soccer" OR "volleyball"
"soccer" || "volleyball"
+要求出现紧接着的词语,例如搜索必须包含soccer而可能包含也可能不包含volleyball的文档:
+soccer volleyball
-禁止紧接着的词语,例如,搜索包含soccer但不包含volleyball的文档:
+soccer -volleyball

转义特殊运算符

特殊运算符有

DisMax查询解析参数

参数行为
q指定不带有特殊字符并将布尔运算符+ 和 - 作为词语修饰符的查询字符串。这个参数不支持*等通配符:
q=apache
q="Apache Lucene"
a.alt在主查询参数q没有指定或为空时定义一个替代查询。这个参数主要用于匹配获取 facet计数的所有文档。
qfqf参数为指定字段分配一个boost因子来提升或降低其在查询中的重要性。例如, qf="firstField^3.4 secondField thirdField^0.2" 分配firstField的boost为3.4,,保持secondField为默认boost,并分配thirdField的boost为0.2。这些boost因子让对 firstField的匹配比secondField更重要,它又变得比 thirdField的匹配更为重要。
mm最小参数定义了必须匹配的可选从句的最小数量。在q 参数中指定的词语或词组被看作可选从句,除非前置了布尔值 AND 或 OR。
mm的可用值为整型(正值或负值)、百分比(正值或负值)、简单或多条件表达式。
mm的默认值是100%,它表示所有的从句必须都匹配。
pf词组字段 (pf)参数在所有q参数中的词语在文档中紧密相邻时会提升打分。
ps词组间隔(ps)参数指定词语匹配pf参数中所指定词组所偏移的位置数量
qs类似于针对pf的ps参数。查询词组间隔 (qs)定义用户通过qf参数显式包含在用户查询字符串中词组查询的间隔量。
tie平分器(tie breaker)参数指定在查询词语在文档中匹配一个以上字段时用作平分器的浮点值(应当是小于1的值) 。
bq Boost Query (bq)参数指定用于添加到用户主查询中影响打分的额外及可选的查询从句。例如,如果你想要为近期文档增加关联度:
q=apachebq=date:[NOW/DAY-1YEAR TO NOW/DAY]
也可使用多个bq参数来用于在需要将查询解析为单独从句时通过单独的提升
bfBoost Functions (bf) 参数指定 将添加到用户主查询中影响打分的函数(带有可选 boost)。任意由 Solr 原生支持的函数都与 boost 值一起使用。例如,如果你想要先显示近期的文档,语法如下:
bf=recip(rord(createddate),1,100,100)

注:boost 拟译为加权、激励

eDisMax查询解析参数

参数行为默认值
sow在空格处分隔。可选的值有true和false。一旦我们将其设为 true,文本分析会针对每个独立的空格分隔词进行。false
mm.autoRelax在一些从句像停止词那样删除或从句的删除不影响搜索时释放从句。在使用mm.autoRelax参数时我们需要当心,因为有时会得到意想外的结果。可用值有 true和false。false
boost一个多值字段列表解析为查询,将打分乘上针对所有匹配文档主查询的打分。
lowercaseOperators将小写的and和 or视频与 AND 和 OR一样的运算符false
pf2一个带有可选权重的多值字段列表。它类似于pf,但基于词语shingle对。
pf3一个带有可选权重的多值字段列表,基于word的三值shingle。它类似于 pf,不同点是它不为输入中所有说事情呢 的每个字段构建词组,而是对词语shingle的每三个的每个字段构建一组词组。
psps参数指定查询中的多少个词汇位置可通过视作匹配词组字段关闭。
ps2类似于 ps但重载用于 pf2的间隔因子。如未指定,则使用ps。
ps3类似于ps但重载用于 pf3的间隔因子。如未指定,则使用ps。
stopwords告诉Solr禁用查询分析器中配置的StopFilterFactory。可用的值有 true 和 false。False会禁用 StopFilterFactory.true
uf指定终端用户允许显示查询哪个schema字段。允许所有字段或 uf=*

通过 API 添加、修改、删除字段

同理,还可使用add-dynamic-field, delete-dynamic-field, replace-dynamic-field及add-field-type, delete-field-type, replace-field-type,还有add-copy-field, delete-copy-field

列出字段:

其它还有/name, /version/,  /uniquekey, /similarity

Schemaless

基础文本分析流程:

  • 删除停止词
  • 添加近义词
  • 使用单词词根
  • 设置所有为小写

Solr的工具

  • Analyzer:决定文本并生成对应的令牌流
  • Tokenizer:通过分隔符(如空格)分隔输入字符串生成信息流
  • Filter
    • 添加:添加令牌到流中,如添加近义词
    • 删除:从流中删除令牌,如停止词
    • 转化:将令牌从一种形式转化为另一种形式,如大写转为小写

如:

Tokenizers

tokenizer是Solr所提供用于分词(tokenization)处理的工具,通过分隔符将文本流打断为分词,生成分词流。

  • StandardTokenizerFactory:空格和标点符号(逗号、点号、破折号、分号、冒号、井号和@)作为分隔符
  • WhitespaceTokenizerFactory:以空格作为分隔符
  • ClassicTokenizerFactory:空格和标点符号作为分隔符:非空格后点号不作为令牌的一部分;破折号不接数字则进行分隔;保留域名和邮箱作为单个令牌
  • KeywordTokenizerFactory:完整的输入字符串作为单个令牌
  • LowerCaseTokenizerFactory:将空格和非字母作为分隔符,最后将字母转为小写
  • LetterTokenizerFactory:丢弃所有非字母,使用相邻字母生成令牌
  • NGramTokenizerFactory:minGramSize=”2″ maxGramSize=”3″
  • EdgeNGramTokenizerFactory

Filters

过滤器主要处理添加(如近义词)、删除(如停止词)和转换(如大小写转换)。

  • StopFilterFactory:去除停止词words=”lang/stopwords_en.txt”
  • LowerCaseFilterFactory
  • ClassicFilterFactory:配合ClassicTokenizerFactory使用,删除点号和所有格中的 ‘s
  • SynonymFilterFactory:已淘汰,推荐使用SynonymGraphFilterFactory
  • SynonymGraphFilterFactory:synonyms=”synonyms.txt”(逗号分隔,如dumb,stupid,dull,匹配左侧、替换右侧:smart,clever,bright => intelligent,genius),索引阶段还必须定义FlattenGraphFilterFactory(对所有 Graph Filter 都必须要有)
  • ASCIIFoldingFilterFactory
  • KeepWordFilterFactory:words=”keepwords.txt”,仅保留列表中的令牌
  • KStemFilterFactory:removing removed都会转换为 remove
  • KeywordMarkerFilterFactory:protected=”protwords.txt”,保留列表中的非词根形式,如transforming
  • WordDelimiterGraphFilterFactory:KnowMore-> Know, More
  • CharFilter
    • solr.MappingCharFilterFactory
    • solr.HTMLStripCharFilterFactory
    • solr.ICUNormalizer2CharFilterFactory
    • solr.PatternReplaceCharFilterFactor

多语言

方法一:managed-schema

方法二:solr.xml

音标匹配

Beider-Morse Phonetic Matching (BMPM)

BeiderMorseFilterFactory:如Taylor, Tailer, and Tailor

 

常见问题

1、*** [WARN] *** Your open file limit is currently 1024.
It should be set to 65000 to avoid operational disruption.

2、关于 log4j 漏洞问题

这次漏洞网上评论为“核弹级”,影响项目非常之多,Solr对应的 log4j 包位于:solr/server/lib/ext/目录下,将相应文件替换为log4j-2.15.0-rc2或之后的版本,重新启动 solr。

其它临时解决方案:

 

 

喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址