欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

elasticsearch倒排索引原理与中文分词器

程序员文章站 2022-04-28 18:11:11
...

1. 索引的方式:

1.1 正向索引
正排表是以文档的ID为关键字,表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档。
这种组织方法在建立索引的时候结构比较简单,建立比较方便且易于维护;因为索引是基于文档建立的,若是有新的文档加入,直接为该文档建立一个新的索引块,挂接在原来索引文件的后面。若是有文档删除,则直接找到该文档号文档对应的索引信息,将其直接删除。但是在查询的时候需对所有的文档进行扫描以确保没有遗漏,这样就使得检索时间大大延长,检索效率低下。
尽管正排表的工作原理非常的简单,但是由于其检索效率太低,除非在特定情况下,否则实用性价值不大。
1.2 倒排索引
倒排表以字或词为关键字进行索引,表中关键字所对应的记录表项记录了出现这个字或词的所有文档,一个表项就是一个字表段,它记录该文档的ID和字符在该文档中出现的位置情况。
由于每个字或词对应的文档数量在动态变化,所以倒排表的建立和维护都较为复杂,但是在查询的时候由于可以一次得到查询关键字所对应的所有文档,所以效率高于正排表。在全文检索中,检索的快速响应是一个最为关键的性能,而索引建立由于在后台进行,尽管效率相对低一些,但不会影响整个搜索引擎的效率。

1.3 总结
正排索引是从文档到关键字的映射(已知文档求关键字),倒排索引是从关键字到文档的映射(已知关键字求文档)。通俗的来说,正向索引可以看作是查找所有文档,然后再去寻找关键字,而倒排索引是通过关键字做索引,然后找索引所对应的文档。
倒排索引elasticsearch倒排索引原理与中文分词器

2. 高级查询

根据id进行查询 
GET /mymayikt/user/12
查询当前所有类型的文档 
GET /mymayikt/user/_search

根据多个ID批量查询 
查询多个id分别为12
GET /mymayikt/user/_mget
{
  "ids":["1","2"]
  
}

复杂条件查询
查询年龄为年龄21岁

GET /mymayikt/user/_search?q=age:21

查询年龄30岁-60岁之间

GET /mymayikt/user/_search?q=age[30 TO 60]
注意:TO 一定要大写

查询年龄30岁-60岁之间 并且年龄降序、从0条数据到第1条数据

GET /mymayikt/user/_search?q=age[30 TO 60]&sort=age:desc&from=0&size=1

查询年龄30岁-60岁之间 并且年龄降序、从0条数据到第1条数据,展示name和age字段

GET /mymayikt/user/_search?q=age[30 TO 60]&sort=age:desc&from=0&size=1
&_source=name,age

Dsl语言查询与过滤
什么是DSL语言
es中的查询请求有两种方式,一种是简易版的查询,另外一种是使用JSON完整的请求体,叫做结构化查询(DSL)。
由于DSL查询更为直观也更为简易,所以大都使用这种方式。
DSL查询是POST过去一个json,由于post的请求是json格式的,所以存在很多灵活性,也有很多形式。

根据名称精确查询姓名

GET mymayikt/user/_search
{
  "query": {
    "term": {
      "name": "xiaoming"
    }
  }
  
}

##term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇
根据汽车名称模糊查询

GET /mymayikt/user/_search
{
  "from": 0,
  "size": 2, 
  "query": {
    "match": {
      
        "car": "奥迪"
      }
  }
}

####match查询相当于模糊匹配,只包含其中一部分关键词就行

Term与Match区别

Term查询不会对字段进行分词查询,会采用精确匹配。
Match会根据该字段的分词器,进行分词查询。

使用filter过滤年龄

GET /mymayikt/user/_search
{
	"query": {
		"bool": {
			"must": [{
				"match_all": {}
			}],
			"filter": {
				"range": {
					"age": {
						"gt": 21,
						"lte": 51
					}
				}

			}

		}

	},
	"from": 0,
	"size": 10,
	"_source": ["name", "age"]

}

3.分词器

3.1 什么是分词器

因为Elasticsearch中默认的标准分词器分词器对中文分词不是很友好,会将中文词语拆分成一个一个中文的汉子。因此引入中文分词器-es-ik插件

演示传统分词器
http://192.168.223.130:9200/_analyze
{
“analyzer”: “standard”,
“text”: “奥迪a4l”
}
elasticsearch倒排索引原理与中文分词器

下载地址: https://github.com/medcl/elasticsearch-analysis-ik/releases
注意: es-ik分词插件版本一定要和es安装的版本对应
第一步:下载es的IK插件(资料中有)命名改为ik插件
第二步: 上传到/usr/local/elasticsearch-6.4.3/plugins
第三步: 重启elasticsearch即可

http://192.168.223.130:9200/_analyze
{
“analyzer”: “ik_smart”,
“text”: “奥迪”
}

elasticsearch倒排索引原理与中文分词器

自定义扩展字典

/usr/local/elasticsearch-6.4.3/plugins/ik/config目录下
mkdir custom
vi custom/new_word.dic
老铁
王者荣耀
洪荒之力
共有产权房
一带一路
余胜军

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

文档映射
已经把ElasticSearch的核心概念和关系数据库做了一个对比,索引(index)相当于数据库,类型(type)相当于数据表,映射(Mapping)相当于数据表的表结构。ElasticSearch中的映射(Mapping)用来定义一个文档,可以定义所包含的字段以及字段的类型、分词器及属性等等。
文档映射就是给文档中的字段指定字段类型、分词器。
使用GET /mymayikt/user/_mapping

映射的分类
动态映射

我们知道,在关系数据库中,需要事先创建数据库,然后在该数据库实例下创建数据表,然后才能在该数据表中插入数据。而ElasticSearch中不需要事先定义映射(Mapping),文档写入ElasticSearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
静态映射
在ElasticSearch中也可以事先定义好映射,包含文档的各个字段及其类型等,这种方式称之为静态映射。
ES类型支持

基本类型
符串:string,string类型包含 text 和 keyword。

text:该类型被用来索引长文本,在创建索引前会将这些文本进行分词,转化为词的组合,建立索引;允许es来检索这些词,text类型不能用来排序和聚合。
keyword:该类型不需要进行分词,可以被用来检索过滤、排序和聚合,keyword类型自读那只能用本身来进行检索(不可用text分词后的模糊检索)。
注意: keyword类型不能分词,Text类型可以分词查询
数指型:long、integer、short、byte、double、float
日期型:date
布尔型:boolean
二进制型:binary
数组类型(Array datatype)
复杂类型
地理位置类型(Geo datatypes)
地理坐标类型(Geo-point datatype):geo_point 用于经纬度坐标
地理形状类型(Geo-Shape datatype):geo_shape 用于类似于多边形的复杂形状

特定类型(Specialised datatypes)
Pv4 类型(IPv4 datatype):ip 用于IPv4 地址
Completion 类型(Completion datatype):completion 提供自动补全建议
Token count 类型(Token count datatype):token_count 用于统计做子标记的字段的index数目,该值会一直增加,不会因为过滤条件而减少
mapper-murmur3 类型:通过插件,可以通过_murmur3_来计算index的哈希值
附加类型(Attachment datatype):采用mapper-attachments插件,可支持_attachments_索引,例如 Microsoft office 格式,Open Documnet 格式, ePub,HTML

Analyzer 索引分词器,索引创建的时候使用的分词器 比如ik_smart
Search_analyzer 搜索字段的值时,指定的分词器

创建文档类型并且指定类型

POST /mymayikt/_mapping/user
{
  "user":{
    "properties":{
       "age":{
         "type":"integer"
       },
        "sex":{
         "type":"integer"
       },
       "name":{
         "type":"text",
         "analyzer":"ik_smart",
         "search_analyzer":"ik_smart"
       },
       "car":{
         "type":"keyword"
      
       }
    }
  }
  
}
http://192.168.223.130:9200/_cat/nodes?pretty
请求地址/索引/_settings
http://192.168.223.130:9200/mymayikt/_settings