Mrli
别装作很努力,
因为结局不会陪你演戏。
Contacts:
QQ博客园

总得学点Elasticsearch吧

2022/04/12
Word count: 2,569 | Reading time: 11min

倒排索引

反向索引(inverted index)更熟悉的名字是倒排索引。

什么是倒排索引: 倒排索引也叫反向索引,通俗来讲正向索引是通过key找value,反向索引则是通过value找key。

举个具体的例子:我们一般是通过标题来找文章内容,即通过目录(正向索引);而反向索引的运用场景就是通过内容来找到是哪一篇文章(标题,作者……),而怎么建立反向索引呢?怎么更快更好地找到结果呢?这个就是搜索引擎做的事了、

正向索引:例如一个“文档1”经过分词,提取了20个关键词,每个关键词都会记录它在文档中的出现次数和出现位置。那我们就可以直接通过对"文档1"Document这个结构进行解析,从而得到每个关键词的信息。

反向索引:那么我们希望通过关键词来找到它在哪几篇“文档”中出现怎么办呢?那么其实在遍历文章的时候,如果当前文章出现了keyword,则对Keyword的结构(简单点可以想成是一个hashmap)添加上这篇文章的信息

再举个生活例子: 当用户在主页上搜索关键词“华为手机”时,假设只存在正向索引(forward index),那么就需要实时扫描完索引库中的所有文档,找出所有包含关键词“华为手机”的文档,再根据打分模型进行打分,排出名次后呈现给用户。因为互联网上收录在搜索引擎中的文档的数目是个天文数字,这样的索引结构根本无法满足实时返回排名结果的要求。

所以,搜索引擎会将正向索引重新构建为倒排索引,即把文件ID对应到关键词的映射转换为关键词到文件ID的映射,每个关键词都对应着一系列的文件,这些文件中都出现这个关键词。从而大大减少了遍历的大小,加快了检索的速度。

本质上是通过设计数据结构,并花了额外的空间去换检索时的时间。

论文查重就是这种的典型应用:B站视频——论文查重是如何实现的——将段落通过标点符号分隔成一个个句子,再将句子每每7个分隔成一个个section,比如长度为9的句子则可以分成3个section,预处理创建preDict={"section1": [doc1, ], "section2": [doc1, ], "section"3: [doc1, ]}的倒排索引,当进行查重时,也是分隔成句子后每每7个字进行检查是否在preDict中,如果在则是知道了在哪些文章中出现(最简单版)。视频后又提出了增加LCS最长公共子串的增强,有效地检验出了添加“的”字or调整字位置的偷鸡方法——建立4字倒排,如果4个字已经出现在了别的文章A里,则把当前句子S1与文章A中的句子S2进行LCS,如果公共子串长度大于7则判定为重复。

搜索引擎——Elasticsearch

Elastic Stack 如果你没有听过,那么 ELK 一定听过。ELK 是三款软件的简称,分别是 ElasticsearchLogstashKibana 组成。那什么是 Elasticsearch呢?——全文搜索是很多网站常见功能,比如 GitHub 站内搜索、JD 商品搜索、B 站视频搜索。Elasticsearch 是当今最火的搜索引擎之一,它的底层基于另外一个 java 开源搜索引擎 Lucene,是一款开源分布式搜索引擎,并且提供了一系列 REST API 操作接口。

ES的核心概念

  1. 索引(Index):ES将数据存储于一个或多个索引中。类比传统的关系型数据库领域来说,索引相当于SQL中的一个数据库,或者一个数据存储方案(schema)。索引由其名称(必须为全小写字符)进行标识。一个ES集群中可以按需创建任意数目的索引。
  2. 类型(type):类型是索引内部的逻辑分区(category/partition),一个索引内部可定义一个或多个类型(type)。类比传统的关系型数据库领域来说,类型相当于“表”。
  3. 文档(Document):文档是索引和搜索的原子单位,它是包含了一个或多个域(Fild)的容器,每个域拥有一个名字及一个或多个值,有多个值的域通常称为“多值域”,文档基于JSON格式进行表示。每个文档可以存储不同的域集,但同一类型下的文档至应该有某种程度上的相似之处。
  4. 集群(Cluster):一个或者多个拥有相同cluster…name配置的节点组成,它们共同承担数据和负载的压力。
  5. 节点(Node):一个运行中的Elasticsearch实例称为一个节点。
    ES集群中的节点有三种不同的类型:
    • 主节点:负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。主节点并不需要涉及到文档级别的变更和搜索等操作。可以通过属性node.masteri进行设置。
    • 数据节点:存储数据和其对应的倒排索引。默认每一个节点都是数据节点(包括主节点),可以通过ode.data属性进行设置。
    • 协调节点:如果node.master和node.data属性均为false,则此节点称为协调节点,用来响应客户请求,均衡每个节点的负载。

Python操作Elasticsearch

安装es库pip install Elasticsearch

参考:

附录

docker 运行 Elasticsearch

根据官网推荐,ES配套 Kibana 只能安装 6.8.19, 所以安装

  1. 拉取镜像:docker pull docker.io/elasticsearch:7.17.2,拉取其他版本可见查看镜像版本:docker-search-tag

  2. es配置文件

    1
    2
    3
    mkdir -p /home/apollo3d/cl/dockerdata/elasticsearch/config 
    mkdir -p /home/apollo3d/cl/dockerdata/elasticsearch/data
    echo "http.host: 0.0.0.0" >> /home/apollo3d/cl/dockerdata/elasticsearch/config/elasticsearch.yml
  3. 启动容器:docker run --name es -p 9200:9200 -p 9300:9300 \ -e "discovery.type=single-node" \ -e ES_JAVA_OPTS="-Xms64m -Xmx512m" \ -v /home/apollo3d/dockerdata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /home/apollo3d/dockerdata/elasticsearch/data:/usr/share/elasticsearch/data \ -v /home/apollo3d/dockerdata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \ -d docker.io/elasticsearch:7.17.2,注:<image_id>可以通过docker images查看刚刚pull下来的镜像;需要去ESC上打开防火墙的指定端口;

  4. 测试:浏览器访问 Elasticsearch 地址:ECS_IP:9200, 如果返回JSON数据则启动正确

  5. 安装 ik 分词器

    1
    2
    3
    4
    5
    6
    # 进入es容器
    $ docker exec -it es bash
    # 下载ik分词器
    $ ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.1.1/elasticsearch-analysis-ik-7.1.1.zip
    # 退出容器
    $ exit
  6. 安装 ik 分词器后重启 Elasticsearch:docker restart es

  7. postman 测试 ik 分词器(注意:把 Content-Type 设置为 application/json )

启动 es-head (可视化界面):

Elasticsearch 5.x后不支持插件,head作为单独服务独立运行。

  1. 拉取镜像:docker pull mobz/elasticsearch-head:5

  2. 启动容器:docker run -d -p 9100:9100 --name esh elasticsearch-head

  3. 访问 es-head:ECS_IP:9100

    当你输入 http://192.168.232.128:9200/ 点击连接时,会发现无法连接。是因为前后端分离开发,存在跨域问题,需要在服务端做 CORS 的配置。我们再次进入 Elasticsearch 容器内部,修改 elasticsearch.yml 配置。

    1
    2
    3
    4
    5
    6
    # 进入容器
    $ docker exec -it es /bin/bash
    [root@7f213e9fb6bb elasticsearch]# vi config/elasticsearch.yml
    # 添加如下两条配置,注意冒号后面有空格,保存并退出。
    http.cors.enabled: true
    http.cors.allow-origin: "*"
  4. 最后退出容器,并重启 Elasticsearch: docker restart esh

  5. 再次访问 es-head,就能看到可视化的界面了。

★启动 kibana(可视化界面)

Kibana 是为 Elasticsearch设计的开源分析和可视化平台。可以使用 Kibana 来搜索,查看存储在 Elasticsearch 索引中的数据并与之交互。你可以很容易实现高级的数据分析和可视化,并且以图表的形式展现出来。

是ELK技术栈中的K,也是ES比较主流的可视化界面,也是官方推荐的

Elasticsearch 5.x后不支持插件,跟Elasticsearch head一样,kibana需要作为单独服务独立运行。

  1. 拉取镜像:docker pull docker.io/kibana:7.17.2

  2. 配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    mkdir -p ~/dockerdata/elk7/kibana/config/
    vi ~/dockerdata/elk7/kibana/config/kibana.yml
    #
    # ** THIS IS AN AUTO-GENERATED FILE **
    #
    # Default Kibana configuration for docker target

    server.name: kibana
    server.host: "0" # 对外访问kibana的地址
    elasticsearch.hosts: [ "http://127.0.0.1:9200" ] # elasticsearch的地址
    xpack.monitoring.ui.container.elasticsearch.enabled: true
  3. 启动容器: docker run -d --name=kibana --restart=always -p 5601:5601 -v ~/dockerdata/elk7/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml kibana:7.17.2

  4. 查看日志: docker logs -f kibana

  5. 等待30秒,如果出现以下信息,说明启动成功了:{"type":"log","@timestamp":"2020-08-27T03:00:28Z","tags":["listening","info"],"pid":6,"message":"Server running at http://0:5601"}

  6. 访问页面:ECS_IP:5601就可以看到Welcome to Kibana啦~

Kibana server is not ready yet问题:

docker-compose:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
version: '3'

services:
elasticsearch:
image: docker.io/elasticsearch:7.17.2
container_name: es2
environment:
- discovery.type=single-node
ports:
- "9200:9200"
- "9300:9300"
kinaba:
image: docker.io/kibana:7.17.2
container_name: kibana2
ports:
- "5601:5601"
volumes:
- /home/apollo3d/cl/dockerdata/elk7/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml
depends_on:
- elasticsearch

查看镜像版本:docker-search-tag

使用自制脚本docker-show-repo-tag.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
#
# Simple script that will display docker repository tags.
#
# Usage:
# $ docker-show-repo-tags.sh ubuntu centos
for Repo in $* ; do
curl -s -S "https://registry.hub.docker.com/v2/repositories/library/$Repo/tags/" | \
sed -e 's/,/,\n/g' -e 's/\[/\[\n/g' | \
grep '"name"' | \
awk -F\" '{print $4;}' | \
sort -fu | \
sed -e "s/^/${Repo}:/"
done

然后在终端运行$ ./docker-show-repo-tags.sh elasticsearch即可获得结果

1
2
3
4
5
...
elasticsearch:8.0.1
elasticsearch:8.1.0
elasticsearch:8.1.1
elasticsearch:8.1.2

Author: Mrli

Link: https://nymrli.top/2022/04/11/总得学点Elasticsearch吧/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
V-P-N(Vmess)与Charles无法共用问题解决
NextPost >
算法与数据结构——滑动窗口、尺取法
CATALOG
  1. 1. 倒排索引
  2. 2. 搜索引擎——Elasticsearch
  3. 3. ES的核心概念
  4. 4. Python操作Elasticsearch
  • 附录
    1. 1. docker 运行 Elasticsearch
    2. 2. 启动 es-head (可视化界面):
    3. 3. ★启动 kibana(可视化界面)
    4. 4. docker-compose:
    5. 5. 查看镜像版本:docker-search-tag