ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。能够达到实时搜索,稳定,可靠,快速,安装使用方便。
我们建立一个网站或应用程序,并要添加搜索功能,令我们受打击的是:搜索工作是很难的。我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全 免费的搜索模式,我们希望能够简单地使用JSON通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。Elasticsearch旨在解决所有这些问题和更多的问题。
我们大多数人使用SQL数据库来执行搜索操作。当然它至少在一定程度上没什么问题。然而,当你越钻越深,就会看到这种方法的局限,如缺乏扩展性、不够灵活、缺乏语言分析(当然SQL数据库的全文检索对此有所作为)等。于Lucene(http://lucene.apache.org)出现了,它的目标是提供一个全文检索的功能库。它非常快速,可扩展,并提供不同语言的分析能力。
全文检索:
生活中的数据包括结构化数据(有固定格式或有限长度的数据)、非结构化输(不定长或无固定格式的数据)还有半结构化数据(XML、HTML等)。
对非结构化数据顺序扫描很慢,对结构化数据的搜索却相对较快(由于结构化数据有一定的结构可以采取一定的搜索算法加快速度),那么把我们的非结构化数据想办法弄得有一定结构不就行了吗?这种想法很天然,却构成了全文检索的基本思路,也即将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。这种先建立索引,再对索引进行搜索的过程就是全文检索。
全文检索大体分两个过程,索引创建(Indexing)和搜索索引(Search)。
* 索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。
* 搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。
详细参考CSDN中链接为http://blog.csdn.net/forfuture1978/archive/2009/10/22/4711308.aspx
基础概念:
1.集群: 一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识,这个名字默认就是 “elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。在产品环境中显式地设定这个名字是一个好 习惯,但是使用默认值来进行测试/开发也是不错的。
2.节点: 一个节点是你集群中的一个服务器,作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况 下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网 络中的哪些服务器对应于Elasticsearch集群中的哪些节点。一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中,这意 味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。
3.索引: 一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名 字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。
4.类型: 在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个 类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类 型,当然,也可以为评论数据定义另一个类型。
5.文档: 一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以 JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。
6.分片:当有大量的文档时,由于内存的限制、硬盘能力、处理能力不足、无法足够快地响应客户端请求等,一个节点可能不够。在这种情况下,数据可以分为较小的称为分片(shard) 的部分(其中每个分片都是一个独立的Apache Lucene索引)。每个分片可以放在不同的服务器上,因此,数据可以在集群的节点中传播。当你查询的索引分布在多个分片上 时,Elasticsearch会把查询发送给每个相关的分片,并将结果合并在一起,而应用程序并不知道分片的存在。此外,多个分片可以加快索引。
7.副本: 为了提高查询吞吐量或实现高可用性,可以使用分片副本。副本(replica)只是一个分片的精确复制,每个分片可以有零个或多个副本。换句话说,Elasticsearch可以有许多相同的分片,其中之一被自动选择去更改索引操作。这种特殊的分片称为主分片(primary shard),其余称为副本分片(replica shard)。在主分片丢失时,例如该分片数据所在服务器不可用,集群将副本提升为新的主分片。
包括接下来Elasticsearch的安装详细参考CSDN中连接为http://blog.csdn.net/cnweike/article/details/33736429/
Lucene评分:
Apache Lucene 默认评分公式解释
对于查询相关性,重点是去理解文档对查询的得分是如何计算出来的
当一个文档经Lucene返回,则意味着该文档与用户提交的查询是匹配的,在这种情况下,每个返回的文档都有一个得分。得分越高,文档相关度越高,至少从Apache Lucene 及其评分公式的角度来看是这样的。
注意:同一文档在不同查询中的得分不具备可比性,不同查询返回文档中的最高分也不具备可比性 ,这是因为文档得分依赖多个因子,除了权重和查询本身的结构,还包括匹配的词项数目,词项所在字段,以及用于规范化的匹配类型
为了计算文档得分,需要考虑以下这些因子:
1.文档权重 : 索引期赋予某个文档的权重值
2.字段权重 : 查询期赋予某个字段的权重值
3.协调因子 : 基于文档中词项命中个数的协调因子,一个文档命中了查询中的词项越多,得分越高
4.逆文档频率 : 一个基于词项的因子,用来告诉评分公式该词项有多么罕见。 逆文档频率越低,词项越罕见
5.长度范数 : 每个字段的基于词项个数的归一化因子 一个字段包含的词项数越多,该因子的权重越低 --这意味着Apache Lucene评分公式更喜欢包含更少词项的字段
6.词频 : 一个基于词项的因子,用来表示一个词项在某个文档中出现的次数。词频越高,文档得分越高
7.查询范数 : 一个基于查询的归一化因子,它等于查询中词项的权重平方和。查询范数使不同查询的得分能相互比较,尽管这种比较通常是困难且不可行的。
TF/IDF评分公式:
Lucene的打分公式很复杂,如下:
得分公式是一个关于查询q和文档d的函数,有两个因子coord和queryNorm并不直接依赖查询词项,而是与查询词项的一个求和公式相乘,求和公式中的每个加数由以下因子连乘所得:词频、逆文档 频率、词项权重、范数。
从公式我们可以导出一些基本规则:
1.越多罕见的词项被匹配上,文档得分越高
2.文档字段越短(包含更少的词项),文档得分越高
3.权重越高(不论是索引期还是查询期赋予的权重值),文档得分越高
所以,Lucene 将最高得分赋予同时满足以下条件的文档:包含多个罕见词项,词项所在字段较短(该字段索引了较少的词项)。
查询改写
如果你之前使用过诸如前缀查询或通配符查询之类的查询类型,那么你会发现这些都是基于多词项的查询,且都涉及查询改写。Elasticsearch使用查询改写是出于对性能的考虑。从Lucene角度来看,所谓的查询改写操作,就是把费时的原始查询类型实例改写成一个性能更高的查询类型实例
举例: 也许用户想找出索引中所有name字段以字母j开头的文档
简单的我们可以在clients索引中执行以下查询:
curl -XGET ‘localhost:9200/clients/_search?pretty‘ -d ‘{ "query" : { "prefix" : { "name" : "j", "rewrite" : "constant_score_boolean" } } }‘
查询改写的属性
之前已经说过可以对任何多词项查询使用rewrite参数来控制查询改写。我们可以将rewrite参数存放在代表查询的JSON对象中
rewrite参数的选项配置:
--scoring_boolean : 该选项将每个生成的词项转化为布尔查询中的一个或从句。这种处理方法比较耗CPU(因为要计算和保存每个词项的得分),而且有些查询生成的词项太多从而超出了布尔查询的限制,默认为1024个从句。改写后的查询会保存计算出来的得分。默认的布尔查询限制可以通过设置elasticsearch.yml文件的Index.query.bool/max_clause_count属性来修改。但须谨记改写后的布尔查询从句越多,查询性能越低
--constant_score_boolean:该选项与前面提到的scoring_boolean类似,但是CPU消耗较少,这是因为该过程并不计算每个从句的得分,而是每个从句得到一个与查询权重相同的常数得分,默认情况下等于1,当然我们也可以通过设置查询权重来改变这个默认值,与scoring_boolean类似,该选项也有布尔从句数的限制
--constant_score_filter: 正如Lucene的javadoc描述的那样,该选项按如下方式改写原始查询:通过顺序遍历每个词项来创建一个私有的过滤器,标记跟每个词项相关的所有文档。命中的文档被赋予一个跟查询权重相关的常量得分。当命中词项数或文档数较大时,该方法比前两种执行速度更快
--top_terms_N : 该选项将每个生成的词项转化为布尔查询中的一个从句,并保存计算出来的得分。与scoring_boolean不同之处在于,该方法只保留了最佳的前N个词项,从而避免超出布尔从句数的限制。
--top_termd_boost_N: 该选项与top_terms_N类似,不同之处在于该选项产生的从句类型为常量得分查询,得分为从句权重。
如何决定何时采用何种查询改写方法?
问题的答案更多取决于应用场景,如果你能接受低精度(往往伴随着高性能),那么可以采用topN查询改写方法。如果你需要更高的查询精度(往往伴随着低性能),那么应该使用布尔方法
二次评分
改变查询返回文档的顺序其中的一个理由就是出于对性能的考虑,例如,在整个文档集上计算文档顺序是非常耗时的,而在原始查询的返回文档子集上做这种计算则非常省事。
Elasticsearch中的二次评分指的是重新计算查询返回文档中指定个数文档的得分。着意味着Elasticsearch会截取查询返回文档的前N个,并使用预定义的二次评分来重新计算它们的得分
二次评分参数配置:
在rescore对象中的查询对象中,必须配置下面这些参数:
1.window_size : 窗口大小,该参数默认设置为from和size参数值之和。它提供了之前提到的N个文档的相关消息。该参数指定了每个分片上参与二次评分的文档个数
2.query_weight : 查询权重值。默认等于1,原始查询的得分与二次评分的得分相加之前将乘以该值
3.rescore_query_weight : 二次评分查询的权重值,默认等于1,二次评分查询的得分在与原始查询得分相加之前将乘以该值。
4.rescore_mode: 二次评分的模式,默认设置为total,elasticsearch0.90.3引入该参数,它定义了二次评分中该文档得分的计算方式,可用的选项有total、max、min、avg、multiply。
当我们设置为total时,文档得分为原始查询得分与二次评分得分之和
当我们设置为max时,文档得分为原始查询得分与二次评分得分之和
当我们设置为min时,文档得分为两次查询得分中的最小值
当我们设置为avg使,文档得分为两次查询得分中的平均值
当我们设置为multiply时,文档得分为两次查询得分的乘积
改变Apache Lucene 的评分方式
自2012年Apache Lucene4.0发布以后,用户便可以改变默认的基于TF/IDF的评分算法了,这是因为Lucene的API做了一些改变,Lucene4.0提供了更多的相似度模型,从而允许我们采用不同的评分方式
可用的相似度模型:
1.Okapi BM25模型:这是一种基于概率模型的相似度模型,可用于估算文档 与给定查询匹配的概率。为了在Elasticsearch中使用它,你需要使用该模型的名字,BM25,一般来说,Okapi BM25模型在短文本文档上的效果最好,因为这种场景中重复词项对文档的总体得分损害较大。
2.随机偏离模型:这是一种基于同名概率模型的相似度模型,为了在elasticsearch中使用它,你需要使用该模型的名字,DFR,一般来说随机偏离模型在类似自然语言的文本上效果更好
3.基于信息的模型: 为了在elasticsearch中使用它,你需要使用该模型的名字,IB。同样,IB模型也在类似自然语言的文本上拥有姣好的效果
以上部分内容参考《深入理解Elasticsearch》
时间: 2024-10-03 01:04:08