全文检索ElasticSearch

wylc123 1年前 ⋅ 787 阅读

一 Elasticsearch的简介和安装
1.1 Elasticsearch是什么
Elaticsearch简称为ES,是一个开源的可扩展的分布式的全文检索引擎,它可以近乎实时的存储、检索数据。本身扩展性很好,可扩展到上百台服务器,处理PB级别的数据。
ES使用Java开发并使用Lucene作为其核心来实现索引和搜索的功能,但是它通过简单的RestfulAPI和javaAPI来隐藏Lucene的复杂性,从而让全文搜索变得简单。

起源:Shay Banon。2004年失业,陪老婆去伦敦学习厨师。失业在家帮老婆写一个菜谱搜索引擎。封装了lucene,做出了开源项目compass。找到工作后,做分布式高性能项目,再封装compass,写出了elasticsearch,使得lucene支持分布式。现在是Elasticsearch创始人兼Elastic首席执行官。

1.2 Elasticsearch的功能
1 分布式的搜索引擎
分布式:Elasticsearch自动将海量数据分散到多台服务器上去存储和检索
2 全文检索
提供模糊搜索等自动度很高的查询方式,并进行相关性排名,高亮等功能
3 数据分析引擎(分组聚合)
最近一周笔记本电脑这种商品销量排名top10的商家有哪些?最近1个月访问量排名top3的新闻板块是哪些?
4 对海量数据进行近实时的处理
因为是分布式架构,Elasticsearch可以采用大量的服务器去存储和检索数据。可以实现秒级别的数据搜索和分析

1.3 Elasticsearch的优点
Elasticsearch的特点是它提供了一个极速的搜索体验。这源于它的高速(speed)。相比较其它的一些大数据引擎,Elasticsearch可以实现秒级的搜索,速度非常有优势。Elasticsearch的cluster是一种分布式的部署,极易扩展(scale )这样很容易使它处理PB级的数据库容量。最重要的是Elasticsearch是它搜索的结果可以按照分数进行排序,它能提供我们最相关的搜索结果(relevance) 。

1.4 安装Elasticsearch Kibana
在阿里云上开放端口

9200 9300 5601

下载镜像

docker pull elasticsearch:7.4.2

docker pull kibana:7.4.2

创建ES实例

mkdir -p /mydata/elasticsearch/config

mkdir -p /mydata/elasticsearch/data

chmod 777 -R /mydata/elasticsearch

echo "http.host: 0.0.0.0">>/mydata/elasticsearch/config/elasticsearch.yml


docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms84m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins -d elasticsearch:7.4.2

创建kibanna实例

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://外网ip:9200 -p 5601:5601 -d kibana:7.4.2

服务器重启 容器自动运行

docker update elasticsearch --restart=always
docker update kibana --restart=always

查看elasticsearch 和 kiban容器是否正在运行

docker ps

1.5 安装中文分词器
下载ik分词器

切换文件夹
cd /usr/software
/usr/software文件夹下创建ik文件夹
mkdir ik
切换到ik文件夹
cd ik
在此文件夹下 下载elasticsearch-analysis-ik-7.4.2.zip中文分词器
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip

解压安装分词器

安装unzip命令
yum install unzip

解压 elasticsearch-analysis-ik-7.4.2.zip
unzip elasticsearch-analysis-ik-7.4.2.zip

删除ik文件夹下的所有的zip文件(删除ik文件夹下的: elasticsearch-analysis-ik-7.4.2.zip)
rm -rf *.zip

#将ik文件夹移动到 /mydata/elasticsearch/plugins文件夹下
cd ..
mv ik /mydata/elasticsearch/plugins

重启下elasticsearch容器
docker restart elasticsearch
查看当前正在运行的容器,如果没有看到elasticsearch
docker ps
使用以下命令查看elasticsearch容器的日志
docker logs elasticsearch

使用kibana测试中文分词器浏览器中输入地址 http://自己的IP地址:5601/

POST _analyze
{
  "analyzer": "ik_max_word",
  "text": "南京市长江大桥"
}

运行结果

{
  "tokens" : [
    {
      "token" : "南京",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "长江大桥",
      "start_offset" : 2,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "长江",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "大桥",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 3
    }
  ]
}


1.6 扩展词典

1 cd /mydata/elasticsearch/plugins/ik/config 目录下,新增自定义词典
vim ext_dict.dic
按i键
输入: 江大桥
按"ESC"键
按:键 输入wq回车
 
2 vi IKAnalyzer.cfg.xml 添加内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 -->
        <entry key="ext_dict">ext_dict.dic</entry>
        <!--用户可以在这里配置自己的扩展停止词字典-->
        <entry key="ext_stopwords"></entry>
        <!--用户可以在这里配置远程扩展字典 -->
        <!-- <entry 
key="remote_ext_dict">http://192.168.211.130:8080/tag.dic</entry> -->
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
 
3 重启elasticsearch容器稍后片刻
docker restart elasticsearch

分词结果中出现了自定义分词 江大桥

{
  "tokens" : [
    {
      "token" : "南京",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "长江大桥",
      "start_offset" : 2,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "长江",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "江大桥",
      "start_offset" : 3,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 3
    },
    {
      "token" : "大桥",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "doc",
      "start_offset" : 6,
      "end_offset" : 9,
      "type" : "ENGLISH",
      "position" : 5
    }
  ]


1.7 Elasticsearch的基本概念

node
节点,部署Elasticsearch程序的服务器

cluster
集群,多个节点组成的架构

index
索引,相当于关系型数据库的database

type
类型,对应于关系型数据库的table

document
文档,类似于关系型数据库的row

文档三元素

_index:文档对应的索引
_type:文档对应的类型
_ID:文档的唯一ID

二 Elasticsearch的快速实战
2.1 查看信息

GET _cat/indices 查看所有索引
GET _cat/nodes 查看所有节点
GET _cat/health 查看ES的健康状态

2.2 新增记录

PUT /索引的名字/类型的名子/主键的值
{
"field":"value",
"field":"value",
.........
}

如果要新增的这条记录在ES中不存在,下面的命令就是一个新增操作。

PUT /schools/student/1
{
"name":"scott"
}

如果要新增的这条记录在ES中存在,下面的命令就是一个更新操作。

PUT /schools/student/1
{
"name":"scott"
}

POST /索引的名字/类型的名子/主键的值
{
"field":"value",
"field":"value",
.........
}

POST 新增数据的时候,可以带id 也可以不带id。如果不带id的话,会自动生成id。如果带了id。这个id在ES中存在当前的POST操作就是一个更新的操作。如果id不存在则是一个新增的操作。

POST PUT 都可以用作新增可以用作修改。 POST 如果不指定id,会自动生成id。PUT必须指定id。
POST PUT 所带的ID相同,则执行更新操作。

乐观锁

ES中有个乐观锁的的概念
seq_no: 表示版本号。当作乐观锁来使用。

PUT /school/student/1?if_seq_no=4&if_primary_term=1
{
"name":"张三",
"age":30
}

2.3 查询记录
查询记录

GET /school/student/1

2.4 更新文档
POST /schools/student/1/_update
{
"doc":{
"name":"ford"
}
}

或者

POST /schools/student/1
{
"name":"ford"
}

或者

PUT /schools/student/1
{
"name":"ford"
}

POST 带_update进行更新的时候,会比较原来的值,如果值没有变化则不更新。
使用_update更新 doc关键字不能缺少,_update只更新指定字段的值,其他的字段不会删除。而其他的更新方式,不赋值的字段会直接删除。如下所示:

更新记录,给记录添加age属性

PUT /schools/student/1
{
"name":"ford",
"age":20
}

使用PUT命令或者是POST不带_update更新

PUT /schools/student/1
{
"name":"ford"
}

在查询此条记录

GET /schools/student/1

会发现age属性没有了。如果使用POST _update更新,则age属性还存在。

2.5 删除文档
delete /索引名/类型/_id

查询索引中的所有记录

GET /索引名/_search
{
  "query": {
    "match_all": {}
  }
}

2.6 删除整个索引
delete /schools

2.7 映射操作
索引创建之后,等于有了关系型数据库中的database。
Elasticsearch7.x取消了索引type类型的设置。不允许指定类型,默认为_doc,但字段仍然是有的,我们需要设置字段的约束信息,叫做字段映射(mapping)

Index-->DataBase
Type(_doc)-->Table
Document-->Row

字段的约束包括但不限于:
字段的数据类型
是否要存储
是否要索引
分词器

2.7.1 查看映射
GET /school/_mapping

三 Elasticsearch的高级应用
3.1 match查询 全文检索

GET /company-index/_search
{
  "query": {
    "match": {
      "job": "Java软件工程师"
    }
  }
}


3.2 match_phrase查询 短语查询 不用分词

GET /company-index/_search
{
  "query": {
    "match_phrase": {
      "job": "Java软件工程师"
    }
  }
}


3.2 multi_match查询

GET /company-index/_search
{
  "query": {
    "multi_match": {
      "query": "李四",
      "fields": ["name","job"]
    }
  }
}


3.3 bool 复合查选
must
文档必须匹配这些条件才能被包含进来
must_not
文档必须不匹配这些条件才能被包含进来
should
如果文档满足should内的条件,将为该文档增加_score,否则无任何影响
filter
使用过滤模式来进行查询
term
精确查询,全文检索使用match,其他非text字段使用term。

GET /company-index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "job": "软件工程师"
          }
        }
      ],
      "must_not": [
        {"match": {
          "name": "李四"
        }}
      ],
      "should": [
        {"range": {
          "payment": {
            "gte": 9000,
            "lte": 20000
          }
        }}
      ],
      "filter": {
        "term":{
          "_id":1
        }
      }
    }
  }
}

相关文章推荐

全部评论: 0

    我有话说: