Lucene中,查询 query 通常被分割为 词项 与 操作符
Lucene中的词项可以是单个词,也可以是一个短语(用双引号括起来的一个词组)
如果查询被设置为要被分析,那么预先选定的分析器将会对查询中的所有词项进行处理
Lucene 中所有数据都存储在 字段 field 中,而字段又是文档的组成单位。
为了实现针对某个字段的查询,用户需要提供字段名称,再加上 冒号 以及 将要对该字段执行查询的从句。
title:Elasticsearch
Elasticsearch 基本概念
Elasticsearch 存储数据的逻辑名字空间,在有分片和副本的情况下可能由一个或多个Lucene索引构成
文档就是 JSON 对象,包含的实际数据 由 键值对 构成。
一旦某个字段上生成了索引,Elasticsearch 就会为那个字段创建一个数据类型,从2.x 版本开始,都会进行严格的类型检查
文档类型代表了一类相似的文档。
类型有两个重要组成部分,一是 名字,二是 字段的数据类型 和 Lucene 配置之间的映射关系
Elasticsearch 类型是以 Lucene 处理文档的这个方式为基础来实现的。一个索引可以有多个类型,这些类型的文档可以存储在相同的索引中。
映射是 Elasticsearch 将复杂 JSON 文档 映射 成 Lucene 需要的扁平化数据的方式。
例如,在 user
类型中, name
字段的映射可以声明这个字段是 string
类型,并且它的值被索引到名叫 name
的倒排索引之前,需要通过 whitespace
分词器分析:
"name": { "type": "string", "analyzer": "whitespace" }
运行在 服务器 上的单个 Elasticsearch 服务实例被称为 节点
- 数据节点
用来存储数据,同时提供对这些数据的搜索功能
2. 主节点
作为监督者控制其他节点的工作
3. 客户端节点
用于查询路由
4. 部落节点
在Elasticsearch1.0版引入的部落节点,可以像桥梁一样将多个集群关联起来,允许在多个集群之上执行几乎所有可以在单集群Elasticsearch上执行的功能
5. Ingest 节点
可用于在构建索引之前,先进行简单的数据转换和处理。
任意一个节点都可以配置成 ingest 节点,而且非常轻量级。
Ingest 节点就是一个Java版的Logstash过滤器,而且是ELasticsearch自带的。
分片就是可以存储在一个 或者 多个节点上的 容器
由 Lucene 段 组成,索引由一个到多个 分片 组成 ,让数据可以分不开。
分片的数量在索引创建时就配置好了,之后无法增减。
分片也有主从之分。
所有改动索引的操作都发生在 主分片上,从分片的数据由主分片复制而来,支持数据快速检索和高可用。如果主分片所在的服务器宕机了,从分片会自动升级为主分片。
副本是为了支持高可用而保存在分片上的另一份数据。副本也有助于提供快速检索
查询在协调节点上进行解析,并用二进制格式序列化到不同节点上。
饱和度是用于限制 词频 在具体文档中的影响的参数。
通过调节参数 k 可以调节词频的影响。
TF-IDF 中饱和度是没有限制的,尽管公式中已经用词频的平方根与对数值相乘,在文档中出现频率更高的词项总会得到更高的 权重。
BM25中引入 k1作为饱和度参数,这样就解决了这个问题
为什么说 BM25 比 TF-IDF 更好一些
饱和点
在 TF-IDF 中由饱和度引起的评分问题:
如果你的布尔查询条件中的 N 个词项里,某一个词项在某份文档中出现了许多次
那么,这份文档的评分就会极高,因为它的词项饱和度 sqrt (termFreq)很弱 。
如果 x or y 是查询条件,而某份文档中 有 1000 个 x 和 0 个 y , TF-IDF 不会考虑 y 从没有出现过,仍然会给它极高的分数。
协调因子 coord 就是用来弱化这种行为的
BM25 天生喜欢那些尽量多的查询词项都出现过的文档
因为它提供了参数 k1 , 可以对词项饱和度提供更有力的控制。
即使查询条件中的某个词出现了很多次,它所增加的分数也远比不上另一个词项出现的次数从 0 变为 1
文档平均长度
TF-IDF 和 BM25 的另一个显著区别是 BM25 也考虑了文档长度的影响。
例如在 1000个词的文档中,旅行 这个词出现了 一两次,那它的内容与旅行应该没有太大关系。但是如果 旅行 这个词 在一篇很短的推文中就出现了两次,那这篇推文肯定和旅行有很大关系。
BM25 针对这种情况进行了补偿,引入了调节参数 b, 文档长度 dl,平均文档长度 avdl 等来调节词项因子