zoukankan      html  css  js  c++  java
  • 全文搜索引擎 Elasticsearch

    写在前面

    最近在学Elasticsearch ,
    我相信只要是接触过开发的都会听过Elasticsearch或ELK这么一个技术。
    主要用来做全文检索或大数据分析等,之前一直处理了解状态。
    所以打算系统学学Elasticsearch ,这也算是我从零学习Elasticsearch的笔记吧。

    1. Elasticsearch 术语介绍

    1.1 文档Document
    - 用户存储在es中的数据文档
    - es存储数据的最小单元
    - 类比于数据库一行数据

    1.2 索引Index
    -由相同字段的文档列表组成
    - 类比于数据库中的表
    ps: es6.0版本之前,索引下面可以新建多个Type,就把这个Index类比于database,
    但是在,6.0版本之后,一个索引下面只能够新建一个Type ,所以类比于表更合适

    1.3 节点Node
    - 一个ES的运行实例,是集群的基本单元

    1.4 集群Cluser
    - 有一个或多个节点组成,对外提供服务

    2.Document 介绍

    Document 主要就是一个Json Object
    json对象有一些字段(Field)组成,常见数据类型:
    - 字符串 :text , keywork
    - 数值型 :long , integer , byte ,double , float , half_float(节省空间) , scaled_float(节省空间)
    - 布尔: boolean
    - 日期:date
    - 二进制 : binary
    - 范围类型 (新的类型): integer_range , float_range , long_tange , double_range, date_range

    注意:每一个文档Document都有一个唯一的ID标识
    - 可以自行指定
    - es 自动生成
    示例Document

    {
    	"remote_ip":"123.207.226.36",
    	"user_name":"liuge",
    	"@timestamp":"2015-05-14T08:23:52.000Z",
    	"request_action":"GET",
    	"http_version":"1.1",
    	"response":"304",
    	"bytes":"0",
    	"referrer":"-",
    	"agent":"-"
    }
    

    每一个Document都有一个MetaData (元数据)
    元数据:用于标注文档的相关信息
    - _index:文档所在的索引名
    - _type: 文档所在的类型名
    - _id:文档的唯一ID
    - _ uid:组合id,由_type和_id组成(6.X版本_type不再起作用)
    - _source:文档的原始Json数据,可以从这里获取每一个字段的内容
    - _all:整合所有字段的内容到该字段,默认禁用,不推荐

    3.Index (索引) 介绍

    类比于table,具有相同结构文档的集合
    - 每个索引都有自己的 mapping 定义 , 用于定义字段名和类型
    一个集群可以有多个索引

    3.RESTful API 介绍

    es集群对外提供RESTful API:用户操作集群中的数据
    - 表现层 状态 转移
    - URI 指定资源 ,如:Index ,Document
    - Http Method 指明资源操作类型,如:GET,POST,PUT,DELETE等
    与es集群资源进行交互的方式:
    方式一:Curl命令行

    curl -XPUT "HTTP://localhost:9200/ceshi/doc/1" -i -H "Content-Type:application/json" -d 
    '
    {
    "username":"liuge",
    "job":"软件开发"
    }
    '
    

    方式二:Kibana DevTools

    PUT /ceshi/doc/1
    {
    	"useranme":"liuge",
    	"job":"软件开发"
    }
    

    4.Mapping 介绍

    Mapping设置,即如何定义数据字段和类型

    ==========Mapping的字段类型(Filed type)===========================
    核心数据类型:
    	- 字符串 :text (会分词), keywork(不会分词)
    	
    	- 数值型 :long , integer , byte ,double , float , half_float(节省空间) , scaled_float(节省空间)
    	
    	- 布尔: boolean
    	
    	- 日期:date
    	
    	- 二进制 : binary
    	
    	- 范围类型 (新的类型): integer_range , float_range , long_tange , double_range, date_range
    复杂的数据类型:
    	- 数组类型 array
    	- Object
    	- 嵌套类型 nested object
    	
    地理位置数据类型:
    	- geo_point
    	- geo_shape
    	
    专用类型:
    	- 记录ip地址
    	- 实现自动补全completion
    	- 记录分次数 token_count
    	- 记录字符串 hash
    	- percolator
    	
    多字段特性:
    	- 允许对同一个字段采用不同的配置,比如分词,常见的实现汉字实现拼音搜索
    	- 实现方式:在汉字中新增一个子字段为pinyin就可以
    

    Kibana DevTools方式:(推荐)

    4.1 自定义一个mapping

    PUT accounts 
    {
    	"settings": {
    		"index": {
    			"number_of_shards" : 1,
    			"number_of_replicas" : 0
    		}	
    	},
    	"mappings":{
    		"doc":{
    			"dynamic":false, # 设置不允许动态添加,结果是,可以插入未定义的字段,但是不能通过未定义字段值来进行查询
    			"properties":{
    				 "user": {
    				  "type": "text",
    				  "analyzer": "ik_max_word",
    				  "search_analyzer": "ik_max_word"
    				},
    				"title": {
    				  "type": "text",
    				  "analyzer": "ik_max_word",
    				  "search_analyzer": "ik_max_word"
    				},
    				"desc": {
    				  "type": "text",
    				  "analyzer": "ik_max_word",
    				  "search_analyzer": "ik_max_word"
    				}	
    			}	
    		}			
    	}
    }
    

    上面代码中,首先新建一个名称为accounts的 Index
    这三个字段都是中文,而且类型都是文本(text),所以需要指定中文分词器,不能使用默认的英文分词器。

    Elastic 的分词器称为 analyzer。我们对每个字段指定分词器。

    "user": {
      "type": "text",
      "analyzer": "ik_max_word",
      "search_analyzer": "ik_max_word"
    }
    

    上面代码中,analyzer是字段文本的分词器,search_analyzer是搜索词的分词器。ik_max_word分词器是插件ik提供的,可以对文本进行最大数量的分词。

    4.2 新增记录,带上id

    PUT accounts/doc/1
    {
      "user": "张三",
      "title": "工程师",
      "desc": "数据库管理"
    }
    

    新增记录的时候,也可以不指定 Id,这时要改成 POST 请求

    POST accounts/doc

    {
      "user": "李四",
      "title": "工程师",
      "desc": "系统管理"
    }
    

    4.3 删除数据

    DELETE accounts/doc/1
    DELETE accounts

    4.4更新记录就是使用 PUT 请求,重新发送一次数据。

    PUT accounts/doc/1
    {
    "user": "张三",
    "title": "工程师",
    "desc": "数据库管理,软件开发"
    }

    4.3 查询数据

    使用 GET 方法,直接请求/Index/Type/_search,就会返回所有记录

    GET accounts/doc/_search

    /Index/Type/id ,返回指定id的记录

    GET accounts/doc/1
    GET accounts/doc/_search
    {
    "query":{
    "term":{
    "_id":"1"
    }
    }
    }

    GET accounts/doc/_search
    {
      "query" : {
        "match" : { 
          "desc" : "管理" 
        }
      },
      "from": 1,
      "size": 1
    }
    

    上面代码使用 Match 查询,指定的匹配条件是desc字段里面包含"软件"这个词
    Elastic 默认一次返回10条结果,可以通过size字段改变这个设置。
    还可以通过from字段,指定位移。
    上面代码指定,从位置1开始(默认是从位置0开始),只返回一条结果。

    逻辑运算or

    GET accounts/doc/_search
    {
      "query" : { "match" : { "desc" : "软件 系统" }}
    }
    

    逻辑运算and

    GET accounts/doc/_search
    {
      "query": {
        "bool": {
          "must": [
            { "match": { "desc": "软件" } },
            { "match": { "desc": "系统" } }
          ]
        }
      }
    }
    

    5 分词介绍

    5.1 Analysis

    分词是指将文本转为一系列单词的过程,也叫作文本分析
    在es里面称为Analysis
    在es中专门负责分词的组件叫做分词器(Analyzer)
    分词器(Analyzer),es会自带一部分词器
    - Character Filters
    - 针对原始的文本进行处理,例如,去除html,a,p,div特殊符号等
    - Tokenizer
    - 将原始的文本按照一定的规则切分为单词
    - Token Filters
    - 把Tokenizer再加工,大小写转换等,没有实际意义的词可以去掉,新增近义词,同义词等

    ps:分词执行的顺序也是从上到下的

    5.2 分词API的使用

    Analyze(分词) API 使用
    es提供的用于测试分词的api接口,验证分词效果
    - 可以直接指定分词器(Analyzer)进行测试
    POST _analyze
    {
    "analyzer":"standard", #这个测试用的standard分词器是es自己带的
    "text":"Hello World!"
    }

    - 可以直接指定索引中的字段进行测试
    	POST test_index/_analyze
    	{
    		"field":"username", # 指定索引(表)的字段
    		"text":"hello world!"
    	}
    
    - 可以自定义分析器进行测试
    	POST _analyze
    	{
    		"analyzer":"standard", #指明自己使用哪一个分词器
    		"filter":["lowercase"], #指明filter处理为小写
    		"text":"HEllo WOrld!"
    	}
    

    5.3 预定义分词器

    es中自带的分词器
    如下:分词器前面讲到,就是由三个部分组成,这里自带的不同也是三个部分组成上不同

    - standard Analyzer
    	- 默认分词器,按照单词的边界切分
    	- Tokenizer 1.standard
    	- Token Filters : 1.standard 2.Loswer case 3.Stop(默认禁用)
    	
    - Simple Analyzer
    	- 切分规则。按照非字母切分,非字母的部分会被删除
    	- Filters 1.Loswer case
    
    - Whitespace Analyzer
    	- 按照空格进行切分
    	
    - Stop Analyzer 
    	- 语气助词等修饰性词语会被移除,比如,the ,an ,的,这那等
    	- 相比于Simple Analyzer 多了修饰性词语的移除
    	- Filters  1.Loswer case 2.stop
    	
    - Keyword Analyzer
    	- 不进行分词操作
    	- 原样输出,当你不想对文本做分词操作的时候
    
    - Pattern Analyzer
    	- 自定义切分的规则,正则匹配
    	- 默认是 W+ ,即非字词的符号作为分隔符,空格 ~ = ‘ 等特殊符号
    
    - Language Analyzer
    	 - 提供了30+ 常见语言的分词器
    
    中文分词:是指将一句中文句子切分为一个个单独的词
    在英文中,句子内单词可以使用空格做明显分隔,
    在中文中,句子内的词语是没有分隔的
    
    常见中文分词系统:
    	- IK
    	- jieba
    	高阶一点的:基于自然语言处理的分词系统
    	- Hanlp
    	- THULAC
    

    5.4 自定义分词器

    当自带的分词器无法满足需求的时候,可以自定义分词
    通过自定义分词的三个部分来实现:

    • Character Filters
    • Tokenizer
    • Token Filters

    5.4.1 Character Filters

    - 针对原始的文本进行处理,例如,去除html,a,p,div特殊符号等
    

    自带的如下:
    - HTML Script 去除html 标签和转换html实体
    - Mapping 进行字符串的替换操作
    - Pattern Replace进行正则匹配替换
    会影响到Tokenizer解析position和offset

    5.4.2 Tokenizer

    -将原始文本按照一定规则切分为单词
    

    自带的如下:
    - standard按照单词进行分割
    - latter 按照非字符类进行分割
    - whitespace 按照空格进行分割
    - UAX URL Email 按照standard 分割 ,但不会分割邮箱和URL
    - NGram 和Edge NGram 连词分割
    - Path Hierachy 按照文件路径进行分割
    测试:

    POST _analyze{
    			"tokenizer":"path_hierachy",
    			"text":"/one/two/three"
    		}
    

    5.4.3 Token Filters

    - 将tokenizer 输出的单词(term )进行增加,删除,修改等操作
    

    自带的如下:
    - lowercase 将所有输出的单词转换为小写
    - stop 删除 stop words
    - NGram 和 Edge Ngram 连词分割
    - Synonym 添加近义词的term
    重要,这里可以实现自动补全的功能

    POST _analyze{
    	"text":"a Hello World!",
    	"tokenizer":"standard",
    	"filter":[
    		"stop",  # 当有多个filter的时候,会依次执行
    		"lowercase",
    		{
    			"type":"ngram",
    			"min_gram":2,
    			"max_gram":4
    		}
    	]
    }
    

    5.5 自定义分词的API

    自定义分词器在索引(具体表)中的设定:

    PUT test_index{
    	"settings":{
    		"analysis":{
    			"char_filter":{},
    			"tokenizer":{},
    			"filter":{},
    			"analyzer":{}
    		}
    	}
    }
    

    demo

    PUT testairbnb
    {
      "settings": {
        "index": {
          "number_of_shards": 1,
          "number_of_replicas": 0,
          "analysis": {
            "analyzer": {
              "autosuggest_analyzer": {
                "filter": [
                  "lowercase",
                  "asciifolding",
                  "autosuggest_filter"
                ],
                "tokenizer": "standard",
                "type": "custom"
              },
              "ngram_analyzer": {
                "filter": [
                  "lowercase",
                  "asciifolding",
                  "ngram_filter"
                ],
                "tokenizer": "standard",
                "type": "custom"
              }
            },
            "filter": {
              "autosuggest_filter": {
                "max_gram": "20",
                "min_gram": "1",
                "token_chars": [
                  "letter",
                  "digit",
                  "punctuation",
                  "symbol"
                ],
                "type": "edge_ngram"
              },
              "ngram_filter": {
                "max_gram": "9",
                "min_gram": "2",
                "token_chars": [
                  "letter",
                  "digit",
                  "punctuation",
                  "symbol"
                ],
                "type": "ngram"
              }
            }
          }
        }
      },
      "mappings": {
        "doc": {
          "dynamic": false,
          "properties": {
            "accommodates": {
              "type": "integer"
            },
            "bathrooms": {
              "type": "integer"
            },
            "bed_type": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "bedrooms": {
              "type": "integer"
            },
            "beds": {
              "type": "integer"
            },
            "date_from": {
              "type": "date",
              "format": "yyyyMMdd"
            },
            "date_to": {
              "type": "date",
              "format": "yyyyMMdd"
            },
            "has_availability": {
              "type": "boolean"
            },
            "host_image": {
              "type": "keyword",
              "ignore_above": 256,
              "index": false
            },
            "host_name": {
              "type": "text",
              "analyzer": "autosuggest_analyzer",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "image": {
              "type": "keyword",
              "ignore_above": 256,
              "index":false
            },
            "listing_url": {
              "type": "keyword",
              "ignore_above": 256
            },
            "location": {
              "type": "geo_point"
            },
            "name": {
              "type": "text",
              "analyzer": "autosuggest_analyzer",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "price": {
              "type": "float"
            },
            "property_type": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "room_type": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        }
      }
    }
    
    

    上面分词的配置中,能够完全实现个性化设定

    参考文章http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html
    参考文章https://coding.imooc.com/class/chapter/181.html

  • 相关阅读:
    MongoDB compass 连接不上远程服务器的解决方法
    art-template 模版引擎
    mongodb数据库的集合关联
    捕获mongoogse 错误信息
    inux下使用自带mail发送邮件告警
    rinted端口转发工具
    windows安装PHP IIS MYSQL
    sql语句查询知识点
    maven加速镜像
    docker启动容器关于防火墙报错
  • 原文地址:https://www.cnblogs.com/liuge36/p/10028348.html
Copyright © 2011-2022 走看看