ES

298 阅读8分钟

ES基础

如何实现商品的搜索
  1. 使用SQL语句的like查询

    • select * from product where name like "%手机%"

    • 当数据量超过千万的时候,效率严重低下

  2. 使用全文检索

    • 主流搜索技术
什么是全文检索
  1. 数据的分类

    • 结构化数据
      • 固定格式、固定长度、数据类型固定(mysql数据库)
    • 非结构化数据
      • 格式不固定、长度不固定、数据类型不固定(磁盘文件)
  2. 结构化数据搜索

    • SQL语句
  3. 非结构化数据的搜索

    • 需求:找出文件中包含hello的文件

      • 1、顺序扫描:数据量非常庞大时性能很差

      • 2、把非结构化数据变成结构化数据

        • 基于结构化数据创建索引,然后再查询
        • 索引:是一个独立的数据结构,b+树。为了提高效率需要独占磁盘空间
        • 停用词:没有意义的词,比如and、a、an、the
        • 全文检索:先对内容进行分词处理(按空格拆分、去除标点、转换大小写、合并相同词、去除停用词,最终获得单词列表,记录单词与文件的对应关系
        • 创建索引,然后查询索引的过程中就叫全文检索
全文检索的应用场景
  1. 搜索引擎
    • 百度、谷歌...
  2. 站内搜索
    • 商品搜索、论坛搜索、微博搜索
  3. 磁盘搜索
    • 查找磁盘上的文件
  4. 只要有搜索的地方都可以使用全文检索

如何实现全文检索

  1. 使用luccene,java中唯一的全文检索技术
    • 是一个全文检索工具包
  2. Solr、ElasticSearch
    • 都是基于luccened的全文检索技术。独立运行、支持集群
    • 实时搜索ES的性能更好
全文检索的流程
  1. 创建索引
    • 采集数据
      • 可以各种新式的数据源
      • 搜索引擎:爬虫
      • 站内搜索:数据库
      • 磁盘搜索:磁盘上的文件
    • 创建文档对象
      • 把原始文档进行封装。Document对象,包含多个Field,不同的document有不同的field
    • 分析文档
      • 对需要分析的field进行分析处理(按空格拆分、去除标点、转换大小写、合并相同词、去除停用词,最终获得单词列表,记录单词与文件的对应关系
    • 创建索引
      • 索引(单词列表)
      • 文档对象(Document文档)
      • 索引与文档的对应关系(倒排序链表)
  2. 查询索引
    • 用户接口
      • 用户输入查询内容
      • 输入可以是一个关键词或者一句话
    • 封装查询条件
      • 把用户输入的内容进行分词处理。得到一个单词列表
      • 需要指定查询的field
      • 查询条件:field:value
    • 执行查询
      • 在索引中根据查询的条件查询对应的字段,找到对应的关键词
      • 如果关键词在索引中存在就能查询到结果,如果不存在就没有结果
      • 根据关键词找到对应的文档ID列表,根据文档ID查询到对应的Document对象
    • 展示结果
      • 关键词的高亮显示、分页处理,根据相关度进行排序
相关度排序
  1. SEO:搜索引擎优化
  2. 两个指标:
    • TF:关键词在文章中出现的频率。TF越大相关度越高。
    • DF:所有文档中关键词出现的频率。DF越大相关度越低。例如 and
    • 根据TF和DF计算出一个相关度的得分,得分越高相关度越高,文档根据相关度得分进行降序排列
ES的多应用场景
  1. 搜索引擎
  2. 存储和分析海量数据(ELK对日志进行存储和分析)
ES下载
  1. 官网下载
  2. 自己下载后保存到自己的百度云等等...
ES安装
  1. docker上安装
    • ElasticSearch
    • ElasticSearch-head客户端:使用nodejs开发的
    • 安装kibana
  2. windows
  3. Linux
  4. Apple
ES索引的创建
  1. 基础概念

    • mysql -> 数据库 -> 表 -> 行 -> 列
    • es -> 索引库 ->(type) -> Document -> field
  2. ES API的使用风格

    • restful
    • 使用不同形式的http方法对资源进行操作。
      • 增:put(post)
      • 删:delete
      • 改:post(put)
      • 查:get
  3. 索引的管理

    • 创建索引库
    • 删除索引库
    • 创建索引的同时设置mapping和Setting
      • 文档格式的定义

      • 文档中包含

        • 字段的名称
        • 数据类型(type)
        • 是否索引(index)
        • 是否存储(store)
        • 是否分词(analyzer)
      • 方法:put

      • url:http://ip:9200/{索引名称}

      • 请求体如下

        {
          "mappings": {
            "properties":{
                    "id":{
                        "type":"long"
                    },
                    "title":{
                        "type":"text",		
                        "analyzer":"ik_smart",
                        "index":true,
                        "store": "true"
                    },
                    "mobile":{
                        "type":"keyword",
                        "store": "true",
                        "index":true
                    },
                    "comment":{
                        "type":"text",		
                        "analyzer":"ik_smart",
                        "store": "true",
                        "index":true
                    }
                }
          },
          "settings": {
            "number_of_shards": 5,
            "number_of_replicas": 1
          }
        }
        
    • 创建索引的设置mapping
      • 方法:put、post

      • url:http://ip:9200/{索引名称}/_mapping

      • 请求体如下

        {
           "properties":{
               "id":{
                   "type":"long"
               },
               "title":{
                   "type":"text",		
                   "analyzer":"standard",
                   "store": "true",
                   "index":true
               },
               "mobile":{
                   "type":"keyword",
                   "store": "true",
                   "index":true
               },
               "comment":{
                   "type":"text",		
                   "analyzer":"standard",
                   "store": "true",
                   "index":true
               }
           }
        }
        
ES文档的管理(增、删、改)
  1. 添加文档

    • 方法:put

    • url:http://ip:9200/{索引名称}/_doc/{id} 其中id与字段id应该设置一样的值

      {
        "id":3,
        "title":"题目23",
        "mobile":"18963607583",
        "comment":"这种方式把查询参数构建成JSON格式的数据"
      }
      
      
  2. 删除文档

  3. 修改文档

    • 方法:post

    • url:http://ip:9200/{索引名称}/_doc/{id} 其中id与字段id应该设置一样的值

      {
        "id":3,
        "title":"题目23修改",
        "mobile":"18963607583修改",
        "comment":"这种方式把查询参数构建成JSON格式的数据修改"
      }
      
  4. 批处理(增、删、改)

    • 方法:post、put

    • url:http://ip:9200/{索引名称}/_bulk

    • 请求体

      {action:{metadata}}
      {请求体数据信息json格式}   //请求数据必须写在一行中
      {action:{metadata}}
      {请求体数据信息json格式}
      {action:{metadata}}
      {请求体数据信息json格式}
      {action:{metadata}}
      {"doc":{请求体数据信息json格式}}
      
    • action对应取值

      • create:创建一个文档,如果文档不存在就创建
      • index:创建一个新的文档,如果文档存在就更新
      • update:批量更新文档
      • delete:批量删除,不需要有请求体
    • metadata对应取值

      • _index:要写入的索引信息
      • _type:要写入的type
      • _id:要写入文档的id
    • 案例

      {"index":{"_id":1}}
      {"id":1, "title":"这是一篇文章", "content":"xxxxx", "comment":"备注信息", "mobile":"13344556677"}
      {"index":{"_id":2}}
      {"id":2, "title":"这是一篇文章", "content":"xxxxx", "comment":"备注信息", "mobile":"13344556677"}
      {"index":{"_id":3}}
      {"id":3, "title":"这是一篇文章", "content":"xxxxx", "comment":"备注信息", "mobile":"13344556677"}
      
ES文档的查询
  1. 根据id查询指定Document

  2. 查询的语法

    • 方法:POST

    • URL:

    • 请求体

      {
      	"query":{
      		"xxxx"
      	}
      }
      
      • 查询全部数据match_all

        {
         "query":{
             "match_all":{}
         }
        }
        
      • 精确匹配term

        {
          "query":{
            "term":{
              "comment":"苹果"
            }
          }
        }
        
      • 模糊匹配1、match

        {
          "query": {
            "match": {
              "title": "题目hahha"
            }
          }
        }
        
      • 模糊匹配2、query_string

        {
          "query": {
            "query_string": {
              "default_field": "title",
              "query": "题目hahha"
            }
          }
        }
        
      • 多字段模糊匹配 multi_match

        {
          "query": {
            "multi_match": {
              "query": "浏览器",
              "fields": ["title","comment"]
            }
          }
        }
        
      • 组合条件查询

        • 逻辑关系:

          • must:必须满足,相当于是AND

          • should:应该满足,相当于OR

          • must_not:必须不能满足,相当于NOT

          • filter:过滤

            • filter查询是不进行打分处理。查询性能好于query
            • filter节点中可以包含多个查询条件,条件之间层层过滤
        {
        	"query":{
        		"bool":{
        			"must":[],
        			"should":[],
        			"must_not":[],
        			"filter":[]
        		}
        	}
        }
        {
        	"query":{
        		"bool":{
        			"must":[
        				{
        					"match":{
        						"title":"apple"
        					}
        				},
        				{
        					"match":{
        						"content":"apple"
        					}
        				}
        			],
                    "filter":[
                        {
                            "term":{
                                "title":"apple"
                            }
                        }
                    ]
        
        		}
        	}	
        }
        
      • 高亮处理

        • 在查询结果中将查询的关键词左右两边分别加上成对的html标签

        • 高亮的处理在查询条件中指定

          {
          	"query":{
          		"bool":{
          			"must":[
          				{
          					"term":{
          						"title":"apple"
          					}
          				}
          			]
          		}
          	},
          	"heightligth":{
          		"fields":{
          			"title":{},
          			"content":{}
          		}
          		"pre_tag":"<em>",
          		"post_tag":"</em>"
          	}	
          }
          
      • 查询结果分页

        {
        	"query":{
        		"multi_match":{
        			"query":"abcdefg",
        			"fields":["title","content"]
        		}
        	},
        	"highlight": {
        		"fields": {
        			"title": {},
                     "content": {}
        		},
        		"pre_tags": "<em>",
        		"post_tags": "</em>"
        	},
        	"from": 10,
        	"size": 5
        }
        
中文分词器
  1. 国产:Ik-analyzer
    • ik_smart:快速分词,速度快,粒度比较粗
    • ik_max_word:最大数量分词,速度慢,粒度细
  2. Ik的使用方法
    • 下载ES对应版本的ik分词器
    • 把分词器解压缩
    • 把解压之后的目录放到{ES}/plugin目录下
    • 重启ES
  3. 索引一旦创建完毕不能修改分词器
  4. field的数据类型
    • 数值类型:int、long、folat、double
    • 字符串
      • text:需要分词的字段必须使用text,只有text类型才能支持分词器
      • keyword:不需要对字段的内容进行分词处理(身份证号、手机号、订单号等)
    • 日期:data
  5. 字段的三个属性
    • 是否分词(analyzer):是否是text类型
    • 是否索引(index)
      • 是否对field的内容进行索引
      • 不分词也可以把field的内容添加到索引中
    • 是否存储(store)
      • 无论是否存储,不影响分词、创建索引、搜索
      • 影响的是能否在查询结果中看到原始内容