学习 ES 的笔记、全文检索、倒排索引、Lucene、ik中文分词器、Kibana使用Dev Tools

感悟

学习即是一个开拓的过程,也是一个重构的过程

新接触的单词
    metric adj.公制的;米制的;公尺的
           n.度量标准
    stats 统计
    blog n.博客;部落格;网络日志
         vi.写博客
         vt.写...博客
    incident 事件
    Archive 美 /ˈɑːrkaɪv/ n.档案馆,档案文件;vt.把...存档
    caution 英 /ˈkɔːʃn/  n.小心,谨慎;警告,警示  vt.警告
    
    // providence 天意;  sparrow n. 麻雀;矮小的人
    // eventually adv.最后,
    // thine 你的
莎士比亚的诗:
    This above all: to thine self be true
    最重要的是:对自己忠实
    There is nothing either good or bad, but thinking makes it so
    事情本没有好与坏之分,只是被思想认为是那样
    There’s a special providence in the fall of a sparrow
    一只麻雀的死是有特殊的天意的
    No matter how dark long, may eventually in the day arrival最终;
    无论天黑有多长,白昼终将到来

知识点一:ES是什么?

  1. ES全称ElasticSearch,是一个基于Lucene的搜索服务器。(其实就是对Lucene进行封装,提供了REST API的操作接口)
  2. ElasticSearch作为一个高度可拓展的开源全文搜索和分析引擎,可用于快速的对大数据进行存储,搜索和分析。
  3. ElasticSearch是基于Java开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。
  4. 根据DB-Engines(数据库引擎)排名显示,ElasticSearch是最受欢迎的企业级搜索引擎。
  5. ElasticSearch和Logstash(数据收集、日志解析引擎)、Kibana(分析和可视化平台)一起开发的。这三个产品被设计成一个集成解决方案,称为“Elastic Stack”(以前被称为ELK技术栈)。

知识点二:ES基本概念

  1. cluster:整个ES默认就是集群状态,整个集群是一个完整的、互备的数据
  2. node:集群中的一个节点,一般只一个进程就是一个node
  3. shard:分片,即使是一个节点也要将数据通过hash算法,分成多个片存放,默认是5片(7.0版本后改为1片)
  4. index:相当于rdbms的database(5.x),对于用户来说是一个逻辑型数据库,虽然物理上会被分多个shard存放,也可能存放在多个node中。6.x 7.x index相当于table
  5. type:类似于rdbms的table,更像class对象,同一Json格式的数据集合。(6.x只允许建立一个,7.x版本舍弃)
  6. document:类似于rdbms的row,面向对象的object
  7. field:字段、属性

知识点三:1.1 什么是全文检索和Lucene?

1)全文检索,倒排索引
Lucene(全文检索技术),Lucene的官网(http://lucene.apache.org/)
数据分析
我们生活中的数据总体分为两种:结构化数据和非结构化数据。
结构化数据:指具有固定格式或有限长度的数据,如数据库中的数据,元数据等
非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件
数据库搜索
数据库搜索很容易实现,通常是使用sql语句进行查询,而且能很快的得到查询结果,为什么呢?因为数据库中的数据存储是有规律的:
有行有列,而且数据格式、数据长度都是固定的
非结构化数据查询方法
一种是顺序扫描(Serial Scanning),另外一种是全文检索(Full-text Search)
顺序扫描法(Serial Scanning):就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,
则此文档为我们要找的文件,接着看下一个文件,至到扫描完所有的文件。
全文检索(Full-text Search):
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这部分[★★★从非结构化数据中提取出的然后重新组织的信息,我们称之为{索引}]。★★★
例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,它就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据(也即对字的解释)。
★★★[这种先建立{索引},再对{索引}进行搜索的过程就叫全文检索(Full-text Search)]。★★★
虽然创建索引的过程是非常耗时的(你想啊,字典制作出来那可是相当费时的),但是索引一旦创建就可以多次使用,全文检索主要是处理查询的,所以耗时创建索引是值得的
总结:全文检索过程分为(创建)索引,(索引)搜索两个过程。
从互联网上、数据库、文件系统中等数据源处获取需要搜索的原始信息,这个过程就是信息采集,信息采集的目的是为了对原始内容进行索引。针对不同的源数据,使用不同的技术进行采集获得原始文档:

1.针对互联网上的数据,可以使用http协议抓取html网页到本地,进而生成一个html文件;
2.针对关系型数据库中的数据,可以连接数据库读取表中的数据;
3.针对文件系统中的数据,可以通过流读取文件系统中的文件。

知识点四:1.2 什么是倒排索引,Lucene实现全文检索的流程是怎样?

倒排索引:创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫{倒排索引结构}。倒排索引结构也叫{反向索引结构},包括索引和文档两个部分,索引即词汇表,它的规模较小,而文档集合较大
Lucene实现全文检索的流程:
1.索引创建和搜索流程图: || 这里随后换成Flowchart ||
原始文档->创建索引-{1.获取文档-2.构建文档对象-3.分析文档(分词)-4.创建索引}->索引库(返回结果->)<-查询索引{1.用户查询接口-2.创建查询-3.执行查询-4.渲染结果}
或者:
数据来源(Web/DB/File System/Manual Input)->获取数据->Index Documents(创建索引)->Index(索引库)->展示结果<-Search Index(搜索索引)<-Get User’s Query(用户查询)
总结:全文检索过程分为(创建)索引,(索引)搜索两个过程。
1.1创建索引=>就是为了用户高效搜索文件名和文件内容包括关键字的文件,索引存储在索引库(Index)中
1.2获得原始文档=>指的是需要索引和搜索的内容(互联网、数据库、磁盘等),必将涉及到[信息采集]过程,目的就是为了对原始内容进行索引,针对不同的源数据,有不同的方法:

  1. 互联网上的数据:可以是用http协议抓取html网页到本地,进而生成一个html文件
  2. 数据库中的数据:可以连接数据读取表中的数据
  3. 针对文件系统中的数据:可以通过流读取文件系统中的文件
    最多的使用1,在互联网上的数据,采集信息使用的软件一般称为爬虫或蜘蛛,也称为网络机器人。
    网络爬虫项目:Nutch、jsoup、Heritrix

1.3创建文档对象
获取原始内容的目的就是对了对其进行索引,在索引前需要将原始内容创建成文档(Document),文档中包括一个一个的域(Field),域中存储内容。
Document和Field是有结构的:
Document中包含了多个Field,例如field_name、field_context、field_path、field_size等
★每个文档都有一个唯一的编号,就是文档ID

1.4分析文档
对域中的对内再进行分析,例如:进行提词、将字母转换为小写、去处标点符号、去除停用词(没有意义的单词)等过程生成最终的语汇单元,我们可以将语汇单元理解为一个一个的单词。
例如:Lucene is a Java full-text search engine.Lucene is not a complete application,but rather a code library and API that can easily
be used to add search capabilities to applications.
从上边这个文档经过分析提取到了:lucene、java、full、sarch、engine、…
每个单词叫一个(Term),例如:文件名中的包含的apache,和文件内容中的apache是不同的term。这里的Field和Term可以看成是Map<K,V>结构,域名(Field)可以看成K,Term可以看成V。
1.5创建索引
对所有文档分析得出的语汇单元进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而得到Document(文档)。
倒排索引:通过词语找文档,这种索引的结构叫{倒排索引}结构。
倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它的规模较小,而文档集合较大。
1.6查询索引
从索引库(Index)中进行搜索的过程。根据关键字找到索引,根据索引找到对应文档。从而找到要搜索的内容。
1.7用户查询接口
1.8创建查询
使用用户提供的关键字构建一个查询对象,查询对象中指定要查询的File文档域,查询关键字等,查询对象会生成具体的查询语法。
1.9执行查询
搜索索引过程:先根据用户提供的关键字,倒排索引按照fileName包含关键字的要求找出索引,根据索引找出文档链表。
例如:查找lucene;生成搜索语法fileName:lucene,搜索过程就是在索引上查找域为filename,并且关键字为lucene的Term,根据Term找到文档id列表。
2.0渲染结果
以一个友好的界面将查询结果展示给用户。比如搜索结果中将关键字高亮显示,百度提供的快照等。

以下只是个人见解

做个了解:
1.ElasticSearch
为用户提供关键字查询的全文搜索功能,实现企业海量数据的处理分析的解决方案,在Hadoop出来之前使用的分析大数据的框架ELK,(ElasticSearch,Logstash,Kibana),这样ElasticSearch=>Hadoop+Hive的功能,Logstash=>Flume,Kibana=>图形化界面,BI工具
2.ElasticSearch特点
2.1天然分片,天然集群
默认自带1份副本,默认5个分片(7.x之后为1个分片)
Master:承担了"协调"、"组合"的工作。流程:首先Master收到用户的请求,然后各个集群节点找到请求对应的那份分片数据,提交给Master,Master收集各个来自节点的分片数据后组合成完整的结果数据,响应给用户(返回给客户端)。
2.2天然索引
各个数据库对待索引的手法:
Hive:天然没索引,有索引没啥用
MySQL:需要什么现成加索引。
ElasticSearch:每一个字段都有索引,因此数据量的膨胀和冗余是非常重的。ElasticSearch无论是占用内存还是磁盘都是大户。
MySQL的索引结构:B+Tree,把Key变成了树形结构,数据的Value在最底层,通过Key的层层查询后才能找到最底层的Value。典型的"通过Key去找Value的"格式。
ElasticSearch的索引结构:[倒排索引]。

实践:使用Kibana - Dev Tools 调用 ES的 REST API:

安装Elasticsearch版本是6.6

elasticsearch-6.6.0

安装kibana的版本也是6.6

kibana-6.6.0-linux-x86_64

ik中文分词器的地址 https://github.com/medcl/elasticsearch-analysis-ik

下载完zip包,放在服务器上,unzip到 your-es-root/plugins/ik
create plugin folder cd your-es-root/plugins/ && mkdir ik
unzip plugin to folder your-es-root/plugins/ik

GET _search
{
  "query": {
    "match_all": {}
  }
}

GET _cat/nodes?v

#green yello red
GET _cat/health?v

#查整个服务器里各个表的状态
GET /_cat/indices?v

#查询某个索引的分片情况
GET /_cat/shards/kibana_sample_data_ecommerce
GET /_cat/shards/movie_index0715

#指定ID添加新数据(document):
#    格式:PUT index/type/_id
#    特点:有就覆盖,没有就插入

#添加新数据(document):
PUT /movie_index0715/movie_type/1
{
    "id":"1",
    "name":"operation red sea",
    "doubanScore":8.5,
    "actorList":[{"id":"1","name":"zhang yi"},
                 {"id":"2","name":"hai qing"},
                 {"id":"3","name":"zhang han yu"}
                ]
}

GET /movie_index0715/_search

DELETE /movie_index0715

PUT /movie_index0715/movie_type/2
{
  "id":2,
  "name":"operation meigong river",
  "doubanScore":8.0,
  "actorList":[{
    "id":"3","name":"zhang han yu"
  }]
}

PUT /movie_index0715/movie_type/3
{
  "id":"3",
  "name":"incident red sea",
  "doubanScore":5.0,
  "actorList":[{
    "id":"4",
    "name":"zhang chen"
  }]
}

DELETE /movie_index0715/movie_type/3

GET /movie_index0715/_search

POST /movie_index0715/movie_type
{
  "id":"3",
  "name":"incident red sea",
  "doubanScore":"5.0",
  "actorList":[{
    "id":"4",
    "name":"zhang chen"
  }]
}

#插入
#PUT 和 POST 区别
#PUT是幂等 POST是非幂等

#修改
# PUT修改全部字段覆盖
# POST可以只改动一个字段
POST /movie_index0715/movie_type/2/_update
{
  "doc":{
    "doubanScore":"8.2"
  }
}

#按条件查询
GET /movie_index0715/_search
{
  "query": {
    "match": {
      "name": "operation red sea"
    }
  }
}

GET /movie_index0715/_search
{
  "query":{
    "match":{
      "actorList.name":"zhang han yu"
    }
  }
}
#这个单纯的match匹配规则是分词匹配,查出的结果包括"zhang han yu"但是有很多分词匹配查到的杂项,此处需要使用精准匹配match_phrase
GET /movie_index0715/_search
{
  "query": {
    "match_phrase": {
      "actorList.name": "zhang han yu"
    }
  }
}

#分词匹配
# operation  [id 1 , offset 0, count 1],[id 2 , offset 0, count 1]
# red
# sea
# meigong
# river
# incident

#_score 相关评分 依据:占比 次数 正相关  其他文档的出现次数 负相关

#查:过滤
#执行的是两次扫描,query和post_filter
GET /movie_index0715/_search
{
  "query": {
    "match": {
      "name": "opeartion red sea"
    }
  },
  "post_filter": {
    "term": {
      "actorList.name.keyword": "hai qing"
    }
  }
}

#bool 混合查询
#一边执行查询的同时 一边执行过滤; 性能上:扫描的次数会少
GET /movie_index0715/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "actorList.name.keyword": "hai qing"
        }
      },
      "must": [
        {
          "match": {
            "name": "operation red sea"
          }
        }
      ]
    }
  }
}

#查看表结构
GET /movie_index0715/_mapping

#过滤 按范围过滤 
#排序sort
#from 页数,size 行号;行号=(页码-1)*页行数
#若只关注结果数据中的其中某个片段可以用_source;"_source": "doubanScore",   
#高亮highlight  document中<em>代表了 页签,可改"pre_tags":<span...>、"post_tags":</span>
#聚合aggs 统计
#常见的聚合类型 sum count avg max min
#aggs底下的terms是分组的意思==groupby
#所有电影的平均分(系列电影的平均分)
#每个演员参与了多少部电影(工作量)(分组后的count) . 演员参演电影的平均分(演技评分)(分组后再进行聚合(aggs))

GET /movie_index0715/_search
{
  "query": {
    "bool": {
      "filter": {
        "range": {
          "doubanScore": {
            "gte": 0, 
            "lte": 111
          }
        }
      },
      "must": [
        {
          "match": {
            "name": "operation red sea"
          }
        }
      ]
    }
  },
  "sort": [
    {
      "doubanScore": {
        "order": "asc"
      }
    }
  ],
  
  "from": 0
  ,"size": 10
  ,"highlight": {
    "fields": {
      "name": {
        "pre_tags":"<span color='red'>",
        "post_tags":"</span>"
      }
      
    }
    }
  
  , "aggs": {
    "avg_score": {
      "avg": {
        "field": "doubanScore"
      }
    }
    ,"actor_movie_count":{
      "terms": {
        "field": "actorList.name.keyword",
        "size": 100
      }
      ,"aggs": {
        "actor_avg_score": {
          "avg": {
            "field": "doubanScore"
          }
        }
        
      }
    }
  }
    
}

#聚合时有些field为何要加.keyword后缀?
#    .keyword是某个字段不需要分词所以才加的,有些term的条件是不需要对其进行分词的比如:filter、aggs等

#测试中文分词器
# analyzer:"ik_smart"
# analyzer:"ik_max_word"
GET _analyze
{
  "text": "我是中国人"
  ,"analyzer": "ik_max_word"
}

GET _analyze
{
  "text": ["红海行动"]
  ,"analyzer": "ik_smart"
}

GET _analyze
{
  "text": ["红海行动"]
  ,"analyzer": "ik_max_word"
}

#插入中文数据
PUT /movie0715_chn/movie/1
{
  "id":1,
  "name":"红海行动",
  "doubanScore":8.5,
  "actorList":[
    {"id":1,"name":"张泽"},
    {"id":2,"name":"海清"},
    {"id":3,"name":"张涵予"}
    ]
}

PUT /movie0715_chn/movie/2
{
  "id":2,
  "name":"湄公河行动",
  "doubanScore":8.0,
  "actorList":[
    {"id":3,"name":"张涵予"}
    ]
}

PUT /movie0715_chn/movie/3
{
  "id":3,
  "name":"红海事件",
  "doubanScore":5.0,
  "actorList":[
    {"id":4,"name":"张晨"}
    ]
}


GET /movie0715_chn/_search
{
  "query": {
    "match": {
      "name": "行"
    }
  }
}

DELETE /movie0715_chn

#基于中文分词搭建索引,规定某个字段使用的ik中文分词器种类"ik_smart","ik_max_word"
PUT /movie0715_chn
{
  "mappings": {
    "movie":{
      "properties":{
        "id":{
          "type":"long"
        },
        "name":{
          "type":"text"
          ,"analyzer":"ik_smart"
        },
        "doubanScore":{
          "type":"double"
        },
        "actorList":{
          "properties":{
            "id":{
              "type":"long"
            },
            "name":{
              "type":"keyword"
            }
          }
        }
      }
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值