ES中的倒排索引与相关性算法计算(TF-IDF/BM25)

一、倒排索引

daopai.png

上图所示左边为正常索引,右边为倒排索引。

倒排索引的核心组成

  • 单词词典(Term Dictionary),记录所有文档的单词,记录单词到到排列表的关联关系。

    • 单词词典一般比较大,可以通过B+树或者哈希拉链法实现,以满足高性能的插入与查询
  • 倒排列表(Posting List)-记录了单词对应的文档结合,由倒排索引项组成

    • 倒排索引项

      • 文档ID
      • 词频TF - 该单词在文档中出现的次数,用于相关性评分
      • 位置(Position) - 单词在文档中分词的位置。用于语句搜索(phrase query)
      • 偏移(offset) - 记录单词的开始结束位置,实现高亮显示

es倒排索引.png

​ 单词Elasticsearch的倒排索引列表

二、相关性与相关性算分

相关性-Relevance

  • 搜索的相关性算分,描述了一个文档和查询语句的匹配程度。ES会对每个匹配查询条件的结果进行算分_score
  • 打分的本质是排序,需要把最符合用户需求的文档排在前面。ES5之前,默认的相关性算分采用TF-IDF,现在采用BM25

词频TF

Term Frequency:检索此在一篇文档中出现的频率

  • 检索词出现的次数除以文档的总字数

度量一条查询和结果文档相关性的简单方法:简单将搜索中的每一个词的TF进行想加,例如:查询 区块链的应用

  • TF(区块链)+TF(的)+TF(应用)

Stop Word

  • “的”在文档中出现了很多次,但是对贡献相关度几乎没有用处,不应该考虑他们的TF

逆文档频率(IDF)

DF:检索词在所有文档中出现的频率

  • “区块链”在相对比较少的文档中出现
  • “应用”在相对比较多的文档中出现
  • “stop word”在大量文档中出现

Inverse Document Frequency:简单说=log(全部文档数/检索词出现过的文档总数)

TF-IDF本质上就是将TF求和变成了加权求和

  • TF(区块链)*IDF(区块链)+TF(的)* IDF(的)+TF(区块链)*IDF(区块链)

TF-IDF.png

TFid公式.png

BM25

TFbm25.png

定制Similarity计算公式

定制评分公式.png

查询小助手

可以通过“explain”参数查看打分状况

POST /testscore/_search
{
  //"explain": true,
  "query": {
    "match": {
      "content":"you"
      //"content": "elasticsearch"
      //"content":"the"
      //"content": "the elasticsearch"
    }
  }
}

使用boost控制相关度评分

boost.png

参考极客时间elasticsearch视频

原创,转发请声明出处啊,亲!

ELK什么

ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案,是三个产品的首字母缩写,分别是ElasticSearch、Logstash 和 Kibana。
ElasticSearch简称ES,它是一个实时的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。它是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,使用 Java 语言编写。
Logstash是一个具有实时传输能力的数据收集引擎,用来进行数据收集(如:读取文本文件)、解析,并将数据发送给ES。
Kibana为 Elasticsearch 提供了分析和可视化的 Web 平台。它可以在 Elasticsearch 的索引中查找,交互数据,并生成各种维度表格、图形。
Filebeat是用于转发和集中日志数据的轻量级传送程序。作为服务器上的代理安装,Filebeat监视您指定的日志文件或位置,收集日志事件,并将它们转发到Elasticsearch或 Logstash进行索引。
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。

整体架构

我将应用部署在了不同的docker容器中,ELK部署在了不同的宿主机上。
ELK整体架构.png

docker->宿主机

首先统一了所有应用的日志输出规范,包括日志的划分,输出格式,命名格式等等。然后将docker内部应用的日志挂载到了宿主机目录,方便filebeat的读取。挂载方式可查看文章《docker数据卷

宿主机log日志->filebeat

因为应用只部署在了一台宿主机上,所以只采用了一个filebeat进行读取,配置文件是分开划分的,整体架构如下:
filbeat读取分发.png
具体Filebeat配置讲解在接下来文章中讲述。

Filebeat->redis

Filebeat将根据设置type的不同将之转发给redis的不同库,做缓存。

Redis->Logstash

logstash开启多个pipeline通道分别读取redis库中的数据,并将之使用fileter解析,最后分发给不同的elasticsearch索引。logstash会在接下来文章中具体讲解。
注:logstash读取完redis库中的数据会将数据删除。
logstash配置.png

Logstash->Elasticseaarch

logstash将数据传输到elasticsearch中时,会在es中自动创建索引,为了使es中的新建索引符合一定格式,我使用了es新建索引模板,指定新建索引的Mapping。会在接下来的文章中具体讲解。

Elasticsearch->Kibana

Kibana通过得到的数据进行统计分析,来实时监控应用的状况。

结论

整体的配置如上述描述,建议大家没事多翻翻官方文档,文档写不清楚的地方,就要自己多配置几次多尝试,毕竟坑都是要一点一点填的。
elastic官网

docker数据卷(数据挂载)

1.引言

docker的镜像是由多个只读的文件系统叠加在一起形成的。当我们在我启动一个容器的时候,docker会加载这些只读层并在这些只读层的上面(栈顶)增加一个读写层。这时如果修改正在运行的容器中已有的文件,那么这个文件将会从只读层复制到读写层。该文件的只读版本还在,只是被上面读写层的该文件的副本隐藏。当删除docker,或者重新启动时,之前的更改将会消失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。

为了很好的实现数据保存和数据共享,Docker提出了Volume这个概念,简单的说就是绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。
摘自:https://www.cnblogs.com/lishanlei/p/9503596.html

2.Docker数据管理

docker在容器中管理数据主要有两种方式:

  • 数据卷(Volumes)
  • 挂载主机目录(Bind mounts)

11227136-e5e2fa69a0e8928f.webp

2.1数据卷

数据卷是一个可供一个或多个容器使用的特殊目录,它绕过UFS,可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 数据卷默认会一直存在,即使容器被删除
    Docker中提供了两种挂载方式,-v和-mount

创建数据卷

docker volume create mydata

查看所有数据卷

docker volume ls

dockerls.png

查看数据卷信息

docker volume inspect mydata

2019-10-16 16-48-19.png

注:Mountpoint为数据在本机存储的位置,如果磁盘存储空间不足可修改此位置

挂载
方式一:

docker run --name xxxx -p 8888:8888 -v /my:/docker -it imagename /bin/bash

--name: 为容器起名字
-p :宿主机端口:docker端口 (端口映射)
-v :宿主机目录:docker目录 (必须为绝对路径)

方式二:
docker run --name xxxx -p 8888:8888 --mount type:volume,source=/src/xxx,target=/xxx /my:/docker -it imagename /bin/bash

type选项,其可以是bind,volume,或 tmpfs。本主题讨论卷,因此类型始终是 volume

注意:使用-v参数时如果本地目录不存在Docker会自动为你创建一个文件夹。使用--mount参数时如果本地目录不存在,Docker会报错。Docker挂载主机目录的默认权限是读写,用户也可以通过增加readonly指定为只读。

  • 如果挂载一个空的数据卷到容器中的一个非空目录中,那么这个目录下的文件会被复制到数据卷中。(我的测试:使用 -v 参数并没有这个效果,需要使--mount参数,如果不符请指正)
  • 如果挂载一个非空的数据卷到容器中的一个目录中,那么容器中的目录中会显示数据卷中的数据。如果原来容器中目录非空,那么这些原始数据会被隐藏掉。

    2.2挂载主机目录

    docker run -it --name c1 -v /宿主机目录:/docker目录 -it imagename /bin/bash
    参考:https://cloud.tencent.com/developer/article/1491692
    https://www.jianshu.com/p/19f12c616d0c

背景介绍
使用elasticsearch时,在集群中进行快照是可能需要使用nfs挂载共享目录,接下来记录下如何使用nfs挂载共享目录。

1.使用root用户进入/etc/exports 文件下配置允许访问的机器的ip以及本机公开的文件目录

/home/xxx/software/es_backup xx.x.x.194(rw)
/home/xxx/software/es_backup xx.x.x.193(rw)

解释:第一个是公开的文件目录,第二个是允许访问机器的ip第三个括号内(rw)是允许读写。

2.启动nfs

service nfs restart

如果不行的话。可以在启动nfs之前,事先启动以下三个命令之一。

service portreserve restart
service rpcbind restart
service portmap restart

解释:以上三个命令启动一个即可,因为linux服务器版本不同,所以不一定哪个起作用。

3.在其他机器挂载此共享目录

mount xxx.xxx.xx.xxx:/home/xx/software/es_backup /home/es/software/test
Unmount /home/es/software/test (取消挂载)

解释:mount 后面跟随的是共享目录主机的ip与文件所在目录,以及你本机的需要放置的目录。

unmount 是你取消挂载这个目录。

4.其他问题

如果nfs出现问题,可能会出现 df ls等等命令无法使用,这样你可以使用

mount |grep nfs 

查看你挂载了的哪些节点,然后将之取消挂载。

最近将博客从wordpress迁移到了typecho记录一下
1.从typecho官网下载给的插件
http://docs.typecho.org/plugins/wordpress-to-typecho
2.根据启用插件按照官网写的步骤进行
中间遇到的问题
1.出现 Database Query Error
解决措施
MySQL5.6的严格模式问题?
然后把严格模式关了,成功转换!
所以解决办法是:
在phpmyadmin/mysql命令行下运行:
代码:

SET GLOBAL sql_mode='';

来源http://forum.typecho.org/viewtopic.php?t=8898