固定排名类似广告第一位,搜索第二位
- 运用 Pinned query 来提高文档的排名(Pinned query 是 Elasticsearch 7.4.0 版本之后,实现的增强检索功能。 Pinned:中文翻译为“固定”。 Pinned query 则可以解释为——固定某些结果,首页置顶显示的检索方式。将置顶显示的数据通过 bool 组合查询 + boost 提升权重的方式给设置了 float 最大值评分,这样就能保证置顶显示了。MAX_ORGANIC_SCORE 大小为:2 的 127 次幂,是 Elasticsearch float 最大值。 正常查询的评分得分不会超过 MAX_ORGANIC_SCORE, 将固定查询(pinned query)的评分设定为:MAX_ORGANIC_SCORE。原理:将置顶显示的数据通过 bool 组合查询 + boost 提升权重的方式给设置了float 最大值评分,这样就能保证置顶显示了。扩展:这并没有实现基于特定关键词返回特定数据的需求?其实有了 pinned query 再将特定关键词与待置顶显示文章 _id ,建立个一对多的映射关系就可 以实现。映射关系可以自己内存维护或者借助 redis 实现都可以。)
关键词的数据提供统计图表,包括舆情走势、词云图、情感分布、情绪走势
- Elasticsearch(以下简称:ES)的 Query 以及 aggregation 功能,采集的数据源包括微博、微信、新闻网页、论坛、自媒体平台、短视频等平台的数 据,每天新增去重数据量在 1 亿+,每条数据在经过结构化,以及经过 NLP(自然语言 处理)之后,超过 150 个字段,比如,文章标题、发布时间、发布作者、发布平台、新 闻分类、新闻提及地域、新闻情绪等。由于业务端需要对这些数据进行实时检索,对不 同平台的数据实时聚合,各平台的数据量分布也有很大的差异,所以按照平台进行拆分, 而不是把所有的数据放到一个大的索引里面。
分词器
- IK(ik_max_word)分词器,占用磁盘空间最小。 Standard 分词器,与 ik_max_word 相差不大,比 ik_max_word 分词方式只增 加了 5% 左右。 N-gram 占用空间比较大,相对于 ik_max_word, 当 n=3,4,5 时,占用空间, 分别是 ik_max_word 的 2 倍、3 倍、4 倍 左右。
数据索引层
- 冷数据集群,选择价格相对低廉的 SAS 盘作为索引的存储介质, 提供离线的数据 下载,以及对响应时间不敏感,且时间周期跨度较长的检索、聚合统计等。 热数据集群,选择 SSD 盘作为索引的存储介质,每个节点 16C、64G 内存, 为了降低运维成本,以及动态扩缩容,我们选择了 阿里云 Elasticsearch 服务。
索引设计
- 把索引按天、按照发文平台进行了拆分,为了方便业务端查询, 根据业务端查询的时间段、发文平台,自动定位到对应的索引,业务端不用关心具体的 索引名称,提高业务端的开发效率, 同时,根据查询时间范围,动态查找对应的索引, 并在查询时指定到具体的索引,提高查询的速度,避免无效的索引扫描。
热门主题词
- 通过一个事件的热门主题词,可以直观的了解到一个事件的大概内容。这里也是通 过 ES 的聚合功能实时获取主题词的统计数据。为了能够实时获取主题词的统计数据, 这里用一个事件中提到每个主题词的文档数量,来当作主题词的数量(相当于默认每个 主题词在文档中只出现一次),并没有用每篇文档的主题词的绝对量。这样做有一个好 处,可以使用 ES 的 aggregation 功能实时聚合获取统计数据,再配合 TF-IDF 算法, 计算每个词的相对权重。在设置索引 schema 时,定义了 news_keywords_list 字段, 用于保存单篇文档的 分词结果列表,然后使用如下的语法,就可以快速统计每个词对应的文档数量,通过上面的 DSL 语句,可以快速统计出高频词以及与其相关的文档数量。
图像搜索
- 人脸检测:识别数字图像中的人脸 ,人脸数据编码:将人脸特征转换为数字表示 脸部比对:搜寻和比较脸部特征(可以将面部特征转换为一组数字信息,以便进行存储和分析。Elasticsearch 提供了 dense_vector 数据类型来存储浮点值的 dense vectors。 向量中的最大尺寸数不应超过 2048,这足以存储面部特征表示。使用 face_recognition 库,我们可以从图像中检测人脸,并将人脸特征转换为 128 维向量,让我们执行 getVectorFromPicture.py 以获取 Elastic 创始人图像的面部特征表示。现在,我们可以将面部特征表示存储到 Elasticsearch 中。 它从目录 images_to_be_recognized 中获取需要识 别的文件,并对这个图片进行识别。我们使用 cosineSimilarity 函数来计算给定查询向 量和存储在 Elasticsearch 中的文档向量之间的余弦相似度。 面部识别和搜索可以结合使用,以用于高级用例。 你可以使用 Elasticsearch 构建更复杂的查询,例如 geo_queries,query-dsl-bool-query 和 search-aggregations。将 cosineSimilarity 与其他 Elasticsearch 查询结合使用,可以无限地实现更复杂的用例。
禁用索引
- 默认情况下,Elasticsearch 文档每个字段都会被索引。如果某些字段不需要支持查 询,可以在映射中配置 “index”: false ,减少存储空间占用,并且提升写入速度。尽管 这个字段不能被搜索,但是它并不妨碍做聚合(如果该字段是可以聚合的字段)。
Doc Values
- Doc Values 是在索引时创建的,当字段索引时,Elasticsearch 为了能够快速检索, 会把字段的值加入倒排索引中,同时它也会存储该字段的 Doc Values。 对一个字段进行排序 ,对一个字段进行聚合 ,某些过滤,比如地理位置过滤,某些与字段相关的脚本计算,使用 docvalue_fields 返回搜索结果部分字段值。
Mapping
- 映射(mapping)就像数据库中的 Schema ,描述了文档可能具有的字段或属性、 每个字段的数据类型,比如 text,keyword,integer 或 date ,以及 Lucene 是如何 索引和存储这些字段的。(字符串: text,keyword,整数:byte,short,integer,long,浮点数: float,double ,布尔型: boolean,日期: date,更多的字段类型比如 geo_point,ip,nested等。
Query DSL
- 查询索引包括全文本查询、组合查询、结构化查询等。 通常 Search 与 Filter 区别二者的查询是有区别的: Query 查询 用于解答文档是否存在,并且告知返回文档与查询条件的匹配度,返回 _score 评分 供用户选择。 Filter 查询 只用于返回文档是否与查询匹配,但是不会告诉你匹配度,即不进行评分。在做聚合查询时,filter 经常发挥更大的作用。因为没有评分 Elasticsearch 的处理速度就会提 高,提升了整体响应时间。同时 filter 可以缓存查询结果,而 Query 则不能缓存。must :必须匹配并且返回评分,filter 忽略评分,should 相当于数据库查询中的or,针对 should 有一个特殊的情况,也就是所有的搜索只有 should ,那么必须满足should 里的其中一个才会被搜索到。must_not 为不匹配,相当于不等于。Boosting 用于控制评分相关度相关,可以提升评分也可以降低评分。因为在 negative 命中了查询条件,negative_boost 在 0 到 1 之间时,用于降低评分,相反,大于 1 用于提升评分。Disjunction 查询也被理解为分离最大化查询,指的是将任何与任一查询匹配的文档,作为结果返回,但只将最佳匹配的评分,作为查询的评分结果返回。tie_breaker 字段做什么用呢?它是起到了缓冲的作用(取值范围:0 到 1 之间), Disjunction 查询会将匹配度最高的字段得分,做为整个文档的得分返回,这种情况 其他字段就不起作用了,难免有点走极端。此时就需要 tie_breaker 来做缓存,提 升其他字段的影响力,最终的结果:brandName 评分+ goodsName 评分 *tie_breaker,作为总评分返回。
Function score
- Function score 允许你控制查询评分,是用来控制评分过程的终极武器。最高效的 用法是用过滤器对结果的子集应用不同的函数,同时运用了 filter 的缓存,并且达到控 制评分的过程。score_modemultiply: 默认,分数相乘 avg:平均分数,第一个 function 的分数 max:使用评分最大的分数 min:使用评分最小的分数 avg 举例,如果 2 个函数返回的分数为 1 和 2,并且它们的权重分别为 3 和 4,则他们的评分为:(13+24)/(3+4) 。
关键字解释
- best_fields :默认,匹配 fields,将评分最高的分数做为整个查询的分数返回; most_fields:查询匹配的文档,并且返回各个字段的分数之和的平均值; cross_fields:跨字段匹配,匹配多个字段中是否包含查询词组,对每个字段分别进行打分,然后执行 max 运算获取打分最高的; phrase:以 match_phrase 方式运行查询,并返回最佳匹配的评分做为总评分; phrase_prefix:以 match_phrase_prefix 方式运行查询,并返回最佳匹配的评分做为总评分; bool_prefix:在每个字段上运行 match_bool_prefix 查询,并组合每个字段的评分,详情参考 bool_prefix 以 cross_fields 为例进行实战讲解。Exists 查询 返回包含字段索引值的文档:Fuzzy 查询 返回包含与搜索字词相似的字词的文档,可以用于查询纠错功能。
分布式计分
- 那么搜索引擎是怎么做到的呢?其关键在于打分,搜索引擎在完成关键字匹配后,会基于一定的机制对每条匹配的数据(后称文档)进行打分,得分高的文档表示与本次查询相关度高,就会在最后的结果列表中排在靠前的位置,反之则排名靠后,从而帮助你快速找到你最想要的数据。即词频( TF )和逆文档频率( IDF )。词频( TF ):词条在文档中出现的次数。逆文档频率(IDF ):在同一索引中存在该词条的文档数的倒数。Elasticsearch 的搜索类型有两种,默认的称为QUERY_THEN_FETCH。顾名思义, 它的搜索流程分为两个阶段,分别称之为 Query 和 Fetch 。Query 阶段:Elasticsearch 在收到客户端搜索请求后,会由协调节点将请求分发到对应索引的每个 Shard 上。 每个 Shard 的 Lucene 实例基于本地 Shard 内的 TF/IDF 统计信息,独立完成Shard 内的索引匹配和打分(基于上述公式),并根据打分结果完成单个 Shard内的排序、分页。每个 Shard 将排序分页后的结果集的元数据(文档 ID 和分数,不包含具体的文档内容)返回给协调节点。协调节点完成整体的汇总、排序以及分页,筛选出最终确认返回的搜索结果。 Fetch 阶段: 协调节点根据筛选结果去对应 shard 拉取完整的文档数据整合最终的结果返回给用户客户端 。
GET /my-index-000001/_search?search_type=dfs_query_then_fetch
{ "query": { "query_string": { "query": "三国演义" } } }
explain 来查看得分的说明信息
- 通过增加 “explain”: true,我们可以看到返回的结果集里增加了大量 _explanation 信息: 通过分析 des cription 和 detail s 中信息的描述,我们可以进一步深挖 Elasticsearch 的打分逻辑和我们查询出来的每个文档的得分详情。
GET /my-index-000001/_search?search_type=dfs_query_then_fetch
{ "query": { "query_string": { "query": "三国演义" } },"explain": true }
Painless scripting
- Painless scripting 是一种简单的、安全的针对 Elasticsearch 设计的脚本语言,(if、else、while、do、for、in,continue,break,return,new、try、catch、 throw、this、instanceof。 )
//如果我们想添加一个新字段,而新字段又依赖已有字段,如下所示,我们添加一个 新品牌,品牌的名称为原有品牌的基础上拼接“新品”,就可以使用脚本来实现此业务。
POST my_goods/_update_by_query
{ "script": { "source": "ctx._source.new_brandName = ctx._source.brandName + '新品'" } }
案例:https://github.com/liu-xiao-guo/face_detection_elasticsearch
|