ES — — elasticsearch初探

本文详细介绍Elasticsearch的安装配置及使用方法,包括增删改查、分词器配置、简单及复杂搜索技巧等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ElasticSearch

title_img

一、安装

安装前最好更新一下npm:

npm install -g npm

同时,要求jdk版本 >= 1.8

1、es 安装

我选择的是7.8.1版本,在官网下载自己需要的版本即可:

es_download

下载完解压,在bin目录下双击elasticsearch.bat,等待一会,会出现9200端口,即es运行的端口:

es_start

我们访问网站,若成功显示如下信息,则表示启动成功:

es_9200

出现了,“You Know, for Search”。

接下来解决跨域问题:

在es的config目录下,我们编辑elasticsearch.yml:

es_cors

在最后添加这两句:

http.cors.enabled: true
http.cors.allow-origin: "*"

es_cors_yml

然后重启es即可。

2、es-head 安装

es-head可以与es建立连接,即时查看es相关信息。

最简单的方法是在chrome的商店里添加elastcisearch-head

es_head_webstore

与es连接后大概是这样(我之前已经创建了一些索引):

es_head_start

也可以在github上下载对应版本的release,下载解压后按照readme的步骤安装启动即可,默认使用的端口为9100

3、Kibana 安装

Kibana是es配套的可视化工程模块。

注意要选择对应版本的Kibana:

kibana_download

下载解压后,在对应的bin目录下,运行kibana.bat。等待一段时间(有warning不用管),出现5601端口:

kibana_start

我们访问网站,出现如下界面即代表启动成功

Kibana_start_5601

右下角的console则是我们学习es主要使用的工具

4、es-analysis-ik 插件安装

es-analysis-ik为es扩展的分词器。

现在es安装目录的plugins目录下新建一个名为 ik 的文件夹,然后在github上下载对应版本的release,将下载的zip解压到我们新建的文件夹内即可。

es_analysis_ik_setup

重启es,可以在终端看到 ik 被启用:

es_analysis_ik_start

二、使用

1、analysis-ik 的使用和配置

  • 配置

a.ik分词器增加字典条目

在es主目录的plugins/ik/config目录下:

ik_配置

我们可以更改IKAnalyzer.cfg.xml文件来增加自定义字典(这里添加的扩展字典为我们自己创建的文件:truthahn.dic):

<?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">truthahn.dic</entry>
	 <!--用户可以在这里配置自己的扩展停止词字典-->
	<entry key="ext_stopwords"></entry>
	<!--用户可以在这里配置远程扩展字典 -->
	<!-- <entry key="remote_ext_dict">words_location</entry> -->
	<!--用户可以在这里配置远程扩展停止词字典-->
	<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
  • 使用

es-analysis-ik分词器有ik_smart(最粗粒度拆分)和ik_max_word(最细粒度拆分)两种模式。示例:

进入Kibana的console界面,

ik_smart:

GET _analyze
{
  "analyzer": "ik_smart",
  "text": "火鸡科技至臻体验"
}

ik_ik_smart

ik_max_word:

GET _analyze
{
  "analyzer": "ik_max_word",
  "text": "火鸡科技至臻体验"
}

ik_ik_max_word

由于我们之前添加的truthahn.dic字典中有“火鸡科技”的条目,若没有添加,ik分词器只会识别出“火鸡”和“科技”。

可以看出,相较于ik_smart,ik_max_word会将字典定义的名词进行进一步的拆分。

2、四大操作:增删改查

  • 前置知识

ES五种method:

es_methods_5种

ES类型:

es_type

  • PUT:

进入Kibana的console界面,创建索引:

PUT /ft1/type1/1
{
  "name": "火鸡科技",
  "text": "火鸡科技至臻体验"
}

注意:type类型已经逐渐被丢弃,可以将上面的type1更改为:_doc

PUT /索引名/_doc/文档ID
{请求体}

ik_PUT_ft1

在es-head中可以看到索引创建成功并且写入了数据:

es_PUT_ft1_head

具体内容:

es_PUT_ft1_head2

同时,我们也可以使用mapping设置索引的一些数据的类型:

PUT /ft4
{
  "mappings":{
    "properties":{
      "name":{
        "type":"text"
      },
      "birtyday":{
        "type":"date"
      },
      "age":{
        "type": "long"
      }
    }
  }
}

es_type_mapping

  • DELETE:

删除索引

DELETE ft2
  • POST:

更新索引:

POST /ft1/_update/1/
{
  "doc":{
    "name":"火鸡PLUS+"
  }
}

es_POST_ft1_update

可以看到,更新时索引ft1的_version会递增,同时result返回的也是updated

  • GET:

获取索引规则信息

GET ft1

es_GET_ft1

另外,可以用GET _cat/获取es的其他信息:

GET _cat/health
GET _cat/master
GET _cat/aliases
GET _cat/count
GET _cat/indices

3、简单搜索

我们先创建一系列索引:

PUT /truthahn/_doc/1
{
  "title":"荷塘月色",
  "author":"朱自清",
  "text":"这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的光里,总该另有一番样子吧。月亮渐渐地升高了,墙外马路上孩子们的欢笑,已经听不见了;妻在屋里拍着闰儿,迷迷糊糊地哼着眠歌。我悄悄地披了大衫,带上门出去。沿着荷塘,是一条曲折的小煤屑路。这是一条幽僻的路;白天也少人走,夜晚更加寂寞。荷塘四面,长着许多树,蓊蓊郁郁的。路的一旁,是些杨柳,和一些不知道名字的树。没有月光的晚上,这路上阴森森的,有些怕人。今晚却很好,虽然月光也还是淡淡的。"
}

PUT /truthahn/_doc/2
{
  "title":"背影",
  "author":"朱自清",
  "text":"我与父亲不相见已二年余了,我最不能忘记的是他的背影。那年冬天,祖母死了,父亲的差使也交卸了,正是祸不单行的日子。我从北京到徐州,打算跟着父亲奔丧回家。到徐州见着父亲,看见满院狼藉的东西,又想起祖母,不禁簌簌地流下眼泪。父亲说,“事已如此,不必难过,好在天无绝人之路!”回家变卖典质,父亲还了亏空;又借钱办了丧事。这些日子,家中光景很是惨淡,一半为了丧事,一半为了父亲赋闲。丧事完毕,父亲要到南京谋事,我也要回北京念书,我们便同行。"
}

PUT /truthahn/_doc/3
{
  "title":"曲院风荷",
  "author":"陈璨",
  "text":"六月荷花香满湖,红衣绿扇映清波。木兰舟上如花女,采得莲房爱子多。"
}

es_search_荷塘

然后我们可以开始简单的搜索:

GET /truthahn/_search?q=title:荷塘月色

结果:

es_search_title荷塘结果

发现title中包含关键字“荷”的索引都被查询到了(PS:十分推荐朱良志教授的《曲院风荷》);

如果搜索“月光”,会发现三个索引同时被查询到:

GET /truthahn/_search?q=text:月光

es_search_月光

这是因为上述字段text的类型为text(es会自动识别数据的类型),所以es会对数据使用分词器进行分词,只要包含关键字的一部分即可匹配,同时,我们看到返回的结果中有 _score 字段,"_score"的值越高,则数据与关键字的匹配度越高。

而当我们将对应数据的类型更改为keyword时,es会对keyword类型的数据进行完全匹配:

创建新的索引,所有数据的类型都为keyword:

PUT /llama
{
  "mappings":{
    "properties": {
      "title":{
        "type":"keyword"
      },
      "author":{
        "type": "keyword"
      },
      "text":{
        "type": "keyword"
      }
    }
  }
}

PUT /llama/_doc/1
{
  "title":"荷塘月色",
  "author":"朱自清",
  "text":"这几天心里颇不宁静。今晚在院子里坐着乘凉,忽然想起日日走过的荷塘,在这满月的光里,总该另有一番样子吧。月亮渐渐地升高了,墙外马路上孩子们的欢笑,已经听不见了;妻在屋里拍着闰儿,迷迷糊糊地哼着眠歌。我悄悄地披了大衫,带上门出去。沿着荷塘,是一条曲折的小煤屑路。这是一条幽僻的路;白天也少人走,夜晚更加寂寞。荷塘四面,长着许多树,蓊蓊郁郁的。路的一旁,是些杨柳,和一些不知道名字的树。没有月光的晚上,这路上阴森森的,有些怕人。今晚却很好,虽然月光也还是淡淡的。"
}

PUT /llama/_doc/2
{
  "title":"背影",
  "author":"朱自清",
  "text":"我与父亲不相见已二年余了,我最不能忘记的是他的背影。那年冬天,祖母死了,父亲的差使也交卸了,正是祸不单行的日子。我从北京到徐州,打算跟着父亲奔丧回家。到徐州见着父亲,看见满院狼藉的东西,又想起祖母,不禁簌簌地流下眼泪。父亲说,“事已如此,不必难过,好在天无绝人之路!”回家变卖典质,父亲还了亏空;又借钱办了丧事。这些日子,家中光景很是惨淡,一半为了丧事,一半为了父亲赋闲。丧事完毕,父亲要到南京谋事,我也要回北京念书,我们便同行。"
}

PUT /llama/_doc/3
{
  "title":"曲院风荷",
  "author":"陈璨",
  "text":"六月荷花香满湖,红衣绿扇映清波。木兰舟上如花女,采得莲房爱子多。"
}

truthahn和llama的索引信息:

es_索引_类型比较

当执行

GET /truthahn/_search?q=title:荷塘月色
GET /llama/_search?q=title:荷塘月色

时前者返回结果中value为2,而后者则为1

当执行

GET /truthahn/_search?q=text:荷塘月色
GET /llama/_search?q=text:荷塘月色

时前者返回结果中value为2,而后者则为0

我们也可以通过设置分词器的类型来验证:

keyword类型:

GET _analyze
{
  "analyzer":"keyword",
  "text":"火鸡科技 至臻体验"
}

结果:

{
  "tokens" : [
    {
      "token" : "火鸡科技 至臻体验",
      "start_offset" : 0,
      "end_offset" : 9,
      "type" : "word",
      "position" : 0
    }
  ]
}

standard类型:

GET _analyze
{
  "analyzer":"standard",
  "text":"火鸡科技至臻体验"
}

结果:

{
  "tokens" : [
    {
      "token" : "火",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "<IDEOGRAPHIC>",
      "position" : 0
    },
    {
      "token" : "鸡",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "<IDEOGRAPHIC>",
      "position" : 1
    },
    {
      "token" : "科",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "<IDEOGRAPHIC>",
      "position" : 2
    },
    {
      "token" : "技",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "<IDEOGRAPHIC>",
      "position" : 3
    },
    {
      "token" : "至",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    },
    {
      "token" : "臻",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "<IDEOGRAPHIC>",
      "position" : 5
    },
    {
      "token" : "体",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "<IDEOGRAPHIC>",
      "position" : 6
    },
    {
      "token" : "验",
      "start_offset" : 7,
      "end_offset" : 8,
      "type" : "<IDEOGRAPHIC>",
      "position" : 7
    }
  ]

4、复杂搜索

还是使用上面创建的索引truthahn的数据,进行复杂搜索:

  • match
GET /truthahn/_search
{
  "query": {
    "match": {
      "text": "月光"
    }
  },
  "_source": ["text"]
}

这里的match与

GET /truthahn/_search?q=月光

的规则类似。都是模糊匹配,会先把查询条件进行分词,然后逐个查询。

不同的是"_source"用来规定返回哪些字段,

"_source": ["text"]

说明只返回text字段,而author和name则不返回

  • term

与match相反,term为完全匹配,要求必须包含全部的term字段:

GET /truthahn/_search
{
  "query": {
    "term": {
      "text": "月光"
    }
  }
}

结果:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

这是因为term默认使用标准分词器,这样原文就会被拆分成一个个单字,匹配不到“月光”。如果将条件改为:

"text": "月"

"text": "光"

就可以搜索到了。

  • sort
GET /truthahn/_search
{
  "query": {
    "match": {
      "text": "月光"
    }
  },
  "_source": ["text"],
  "sort": [
    {
      "text.keyword": {
        "order": "asc"
      }
    }
  ]
}

添加“sort”规则,sort能够对返回的数据进行排序,此时返回的_score为null。

es_复杂搜索_排序

  • from&size
GET /truthahn/_search
{
  "query": {
    "match": {
      "text": "月光"
    }
  },
  "_source": ["text"],
  "sort": [
    {
      "text.keyword": {
        "order": "asc"
      }
    }
  ],
  "from":0,
  "size":1
}

添加from和size规则,这两个规则规定返回结果的范围,可以理解成sql语句中的limit,

"from":0,
"size":1

能够获取返回的第一个结果,就类似于

select ... from ... where ... limit 0,1

es_索引_from_size

  • bool

bool规则有must、must_not、should、boost、filter、mininum_should_match等判断逻辑,可以进行多条件查询:

must类似于and、且:

GET /truthahn/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match":{
            "author":"朱自清"
          }
        },
        {
          "match": {
            "text": "赋闲"
          }
        }
      ]
    }
  }
}

es_search_bool

should类似于or、或:

GET /truthahn/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match":{
            "author":"朱自清"
          }
        },
        {
          "match": {
            "text": "赋闲 变卖"
          }
        }
      ]
    }
  }
}

es_复杂搜索_空格多条件

不知大伙有没有注意到,这里的match里可以用空格分隔查询多个条件,实现多条件查询。同时,虽然是should逻辑,但背影的_scroe为6.10,而荷塘月色只有0.83,说明更加匹配。

  • highlight
GET /truthahn/_search
{
  "query": {
    "term": {
      "text": "月"
    }
  },
  "highlight": {
    "fields": {
      "title": {},
      "author": {},
      "text": {}
    }
  }
}

es_search_highlight

可以看到,满足条件的数据都添加了em标签

结语

好久没发博客了,有些写了一半没写完,就搁置了。这次由于工作需要,系统学习了elasticsearch,狂神讲得很好,收获满满。接下来会开始结合es进行相关前后端交互的开发。

感谢

全文搜索引擎 ElasticSearch 还是 Solr?
B站BV号:BV17a4y1x7zq

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TurkeyMan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值