全文检索-ElasticSearch入门

Posted java本渣

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全文检索-ElasticSearch入门相关的知识,希望对你有一定的参考价值。

文章目录

1. 基于Lucene的全文检索

1.1 全文检索概念

    非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行检索,从而达到搜索相对较快的目的。从非结构化数据中提取出来并重新组织的信息,我们称之为索引。

例如:字典中的拼音表、偏旁部首表就相当于字典的索引。

    这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。

注意:索引创建过程十分耗时,但是一旦创建有利于复用。全文检索主要处理的是查询,所以虽然创建索引耗时,但却值得。否则使用顺序扫描的方式去查询非结构化数据是非常慢的。

因此,在大数据量的情况下,如果你需要用到搜索,就可以用到全文检索引擎。


    1998年9月4日,谷歌公司在美国成立,正如大家所说的,它是一家做搜索引擎起家的公司。无独有偶,有个叫 Doug Cutting 的美国工程师,也迷上了搜索引擎,他做了一个用于文本搜索的函数库(可以理解成一个软件的功能组件),名为Lucene(ElasticSearch和Solr都是基于它封装的)。

注:故事来自鲜枣课堂公众号。此外,hadoop的作者也是 Doug Cutting。

    Lucene 是用 Java 编写的信息检索工具包(不包含搜索引擎系统),目的是为各种中小型应用软件增添全文检索功能,因为好用且开源得到了程序员的欢迎。2001年,Lucene 成为了Apache软件基金会jakarta项目的一个子项目

    Nutch 是一个建立在Lucene核心之上的网页搜索应用程序,可以直接download使用。它在Lucene的基础上增加了网络爬虫和一些网页相关的功能,目的就是像谷歌一样从一个简单的站内检索推广到全球网络的搜索上。

注:这里是本人看了B站狂神说相关视频了解到的一个前菜,个人记住了3个词:大数据 = 海量存储 + 计算,除此之外还有一些技术的关联历史,推荐大家去了解下,有利于对技术的发展追溯和认知,因为这是一个大数据的背景,包括我们之后学的ES也是处于这种背景之下。



1.2 全文检索过程



1.3 全文检索相关概念

  1. 索引库

    即将索引存储在磁盘上的一系列文件,里面保存了建立好的索引信息以及文档对象

    一个索引库可类比于数据库中的一张表。

  2. 文档对象

    获取原始内容的目的是为了索引,在创建索引前需要将原始内容创建成文档,文档中包括很多个域,域中存储内容,且每个文档都有唯一的编号,即文档id。

    一个文档可类比于表里的一条记录。

  3. 域对象

    域(Field)是索引库中存储数据的最小单位,其数据类型可以分成数值类型和文本类型两种。一般查询的字段都是文本类型的,域还有如下属性:

    域可以类比成记录的字段。

    • 是否分词

      是否对域的内容进行分词处理,前提是我们要对域的内容进行查询。如果是类似商品编号、商品价格可以不用分词。

      例如,标题——中国人民银行,可以分词为:

      • 标题:中国;
      • 标题:人民;
      • 标题:银行;
      • 标题:中国人民。
    • 是否索引

      将Field分析后的词或整个Field进行索引,只有索引才能搜索到

      例如:商品名称、商品简介分析后进行索引,订单号、身份证号可以不用分词但是也要索引,它们将来都可以作为查询的条件。

    • 是否存储

      是否将Field值存储在文档中,存储在文档中的Field才能从文档中获取到。

      例如商品名、订单号,凡是将来要从文档中获取的域都要存储。

    • term对象

      从文档对象中拆分出来的每个词都是一个term,term中包含两部分:文档域名和单词的内容。

      注意:不同域中拆分出来的统一单词是不同的term,term是创建索引的关键词对象。



1.4 全文检索的使用场景

  1. 搜索的数据对象是大量的非结构化的文本数据。
  2. 文件记录量达到数十万或数百万个甚至更多。
  3. 支持大量基于交互式文本的查询。
  4. 需求非常灵活的全文搜索查询。
  5. 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
  6. 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。



2. ElasticSearch

2.1 ElasticSearch概念

    ElasticSearch(ES)是一个开源的、高扩展的、分布式的全文检索引擎,它可以==近乎实时地存储、检索数据==,并且由于本身扩展性很好,可以扩展到上百台服务器,所以能够处理PB级别的数据。ES 也可以使用 Java 开发,并使用Lucene作为其核心,从而实现所有索引和检索的功能。ES 的目的是通过简单的Restful API 来隐藏Lucene的复杂性,使得全文搜索变得十分简单

注:2016年,ES已经成为了排名第一的搜索引擎类应用。



2.2 ElasticSearch应用案例

  • GitHub:2013年初抛弃了Solr,采用 ElasticSearch 来做PB级别的搜索,“GitHub使用 ElasticSearch 搜索20TB的数据,包括13 亿文件和1300亿行代码”。
  • 百度:目前广泛使用 ElasticSearch 作为文本数据分析,采集百度所有服务器其上的各类指标数据和用户自定义数据,通过对各种数据进行多维分析战术,辅助定位分析实例异常或业务层面异常。单集群最大100台机器,200ES节点,每天导入30TB+数据。
  • 新浪:使用 ElasticSearch 分析处理32亿实时日志。
  • 阿里巴巴:使用 ElasticSearch 构建自己的日志采集和分析体系。
  • ……



2.3 ElasticSearch和Solr对比

  • 都是基于 Lucene 而改造、封装的全文检索引擎;

  • Solr 利用Zookeeper进行分布式管理;ElasticSearch 自身带有分布式协调管理功能

  • Solr 支持更多格式的数据(json、xml、csv…);ElasticSearch 仅支持json数据格式

  • Solr 官方提供更多的功能;ElasticSearch 本身更注重核心功能,高级功能多有第三方插件提供;

    例如:IK分词器、图形化界面需要Kibana友好支持。

  • Solr 在传统的搜索应用中表现优于 ElasticSearch,在处理实时搜索应用时效率低于ElasticSearch。

  • 单纯地对已有的数据进行搜索的时候,Solr更快;当实时建立索引的时候,Solr会产生IO阻塞,查询性能相对较差,ES有明显的优势。

  • 随着数据量的增加,Solr的搜索效率会变得更低,而ES没有明显变化。

  • Solr查询快,但更新索引时慢,适合电商等查询多的应用;ES建立索引快(查询慢)实时性查询快,适合facebook、新浪等搜索。



2.4 ElasticSearch 术语

2.4.1概述

    ElasticSearch 是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在 ElasticSearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。

    借用了一位仁兄的图

注意:和1.3小节有细微差别。一切都是json。在这里提一嘴,不要一上来就记各种名词,容易绕懵(我一开始上来就懵逼了),通过类比进行记忆并理解各自对应的内容、作用即可。


2.4.2 Index 索引

一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。


2.4.3 Type 类型

    在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。

注意:Elasticsearch 6.X中,一个 index 下已经只能包含一个Type,Elasticsearch 7.X中, Type的概念已经被删除了。因为这里的版本用的是6.7.1,所以提一嘴,之后学完高版本之后再回过头来更新。

为什么要删除映射类型?


2.4.4 Document 文档

    一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。在一个Index/Type里面,你可以存储任意多的文档。注意,尽管一个文档物理上存在于一个索引之中,但是文档必须被索引/赋予一个索引的Type(看版本)。


2.4.5 Field 字段

    相当于是数据表的字段,对文档数据根据不同属性进行的分类标识

2.4.6 Mapping 映射

    Mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其它就是处理ES里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。

注意:映射可类比于数据库表格中对字段的定义。


2.4.7 NRT 接近实时

    ElasticSearch 是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒以内)。

2.4.8 Cluster集群

    一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识(一个人就是一个集群!戏精一点的说法就是一人一城既视感hhhh,只不过默认这个集群里只有一个节点而已)。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。

注意:集群名一般默认就是“elasticsearch”,但是在2.5小节中发现默认是”docker-cluster“,这与ES的版本和构建类型有关。后面先统一称之为“elasticsearch”。

2.4.9 Node 节点

    一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对应于Elasticsearch集群中的哪些节点。

    一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。
    在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何 ElasticSearch 节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。


2.4.10 Shards&Replicas 分片和复制

    一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。为了解决这个问题,ElasticSearch提供了将索引划分成多份的能力,这就叫做分片

    当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主要有两方面的原因:

  1. 允许你水平分割/扩展你的内容容量。
  2. 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量。

    至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由ElasticSearch管理,对于作为用户的你来说,这些都是透明的。

注意:实际上,一个分片是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得ES在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。那么像我这种菜鸡第一次看到肯定在想啥又是倒排索引??持续懵逼…

倒排索引(有人说正确的翻译应该叫反转索引):

    ES使用的是一种倒排索引的结构(Lucene底层就用了倒排),这种结构使用于快速的全文搜索。一个索引由文档中所有不重复的列表构成,对于每个词都有一个包含它的文档列表。

​    为了创建倒排索引,我们首先将每个文档拆分成独立的词,然后创建一个包含所有不重复词条的索引列表,然后列出每个词条在哪个文档有出现

    这样的话,我们在搜索某些词的时候,会根据这个列表去查找满足条件的文档,例如,词abc在文档1和文档2都出现了,词def只在文档1出现了,那么我们在搜索abc def 的时候就会搜索到这两个表格,而且文档1的权重(score)更高,因为它更符合条件。

​ 因此,查找倒排索引之后的数据会比直接查原始数据快得多。所以抓住重点,什么是倒排索引:文档key—>词value,查文档的时候就反过来根据词再对文档排一次(权重高低)

总之,一个ES索引(库概念)是由多个Lucene索引组成的(因为多个分片)。一般情况下,说到的索引指的是ES索引而不是Lucene索引。

    在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,ElasticSearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制

    复制之所以重要,有两个主要原因:

  1. 在分片/节点失败的情况下,提供了高可用性。

    因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。

  2. 扩展你的搜索量/吞吐量。

    因为搜索可以在所有的复制上并行运行。总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变分片的数量

    默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。

注意:需要考虑版本的不同,7.0以上不会默认帮你创建分片了,需要自己创建索引的时候设置。


2.5 ElasticSearch安装

这里采用Docker进行安装ES 6.7.1。

  1. Docker拉取ES镜像;

    docker pull elasticsearch:6.7.1
    
  2. 创建ES数据的数据卷目录,并设置权限;

    这里挂载数据卷一定要给权限。

    mkdir -p /data/elasticsearch/data
    
    sudo chmod 777 /data/elasticsearch/
    sudo chmod 777 /data/elasticsearch/data/
    

  3. 后台运行ES容器;

    docker run -d --name elasticsearch \\
    -p 9200:9200 \\
    -p 9300:9300 \\
    -v /data/elasticsearch/data:/usr/share/elasticsearch/data \\
    elasticsearch:6.7.1
    
  4. 遇到ES闪退,查看日志发现最大虚拟内存区域的数量太低了;

    docker logs elasticsearch #查看日志
    
    vim /etc/sysctl.conf #追加以下内容 (限制一个进程可以拥有的VMA(虚拟内存区域)的数量 )
    vm.max_map_count=655360
    
    sysctl -p #修改内核参数马上生效
    
  5. 访问9200端口;

    9200端口是ES的Web管理平台端口,9300是ES的服务默认端口。

    注意:这里使用的构建类型是docker,默认集群名是”docker-cluster“。

  6. 修改elasticsearch.yml文件

    docker exec -it elasticsearch /bin/bash #进入容器
    dir # 查看文件目录
    cd config #进入config目录
    ls #查看文件
    vi elasticsearch.yml #修改elasticsearch.yml文件
    
    node.name: es0 #节点名称
    network.host: 192.168.31.35 #本节点ip地址
    http.host: 0.0.0.0
    transport.host: 0.0.0.0
    
    cluster.name: my-elasticsearch #修改集群名
    node.master: true #是否作为集群的主节点
    node.data: true #是否存储数据
    
    discovery.zen.ping.unicast.hosts: ["192.168.31.35:9300"] #配置集群中节点的位置,节点之间可以相互通信
    
    #跨域设置
    http.cors.enabled: true #默认false
    http.cors.allow-origin: "*"
    
    exit
    docker restart elasticsearch
    

    注:ES中的config/elasticsearch.ymal配置项说明

  7. 设置容器开启自动重启。

    docker update --restart=always elasticsearch
    
  8. 修改JVM内存。

    vi jvm.options
    
    -Xms512m #设置JVM初始可用内存为512M,默认1G
    -Xmx512m #设置JVM最大可用内存为512M,默认1G
    
    exec
    docker restart elasticsearch
    

    注意:也可以在创建容器的时候就指定,即加上:-e ES_JAVA_POTS="-Xms512m -Xmx512m"



2.6 ElasticSearch的客户端操作

    实际开发中,主要有三种方式可以作为 ElasticSearch 服务的客户端:

  • 第一种,elasticsearch-head插件;

    注意:ES需要设置跨域才行。

  • 第二种,使用 ElasticSearch 提供的Restful接口直接访问;

    使用postman进行客户端操作,需要注意的是:

    1. 6.x版本的是否分词设置成 “index”:true或false。
    2. 测试一下标椎分词器的效果需要使用post请求。
  • 第三种,使用 ElasticSearch 提供的API进行访问。


2.7 IK分词器

2.7.1 IK分词器概念

    IKAnalyzer是一个开源的、基于 Java 语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出 了3个大版本。最初,它是以开源项目 Lucene 为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IKAnalyzer3.0则发展为面向 Java 的公用分词组件,独立于 Lucene 项目,同时提供了对 Lucene 的默认优化实现。


2.7.2 IK分词器特性

  1. 采用了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的高速处理能力。
  2. 采用了多子处理器分析模式,支持:英文字母(IP地址、Email、URL)、数字(日期,常用中文数量词,罗马数字,科学计数法),中文词汇(姓名、地名处理)等分词处理。
  3. 对中英联合支持不是很好,在这方面的处理比较麻烦。需再做一次查询,同时是支持个人词条的优化的词典存储,更小的内存占用。
  4. 支持用户词典扩展定义。
  5. 针对Lucene全文检索优化的查询分析器IKQueryParser;采用歧义分析算法优化查询关键字的搜索排列组合,能极大的提高Lucene检索的命中率。

2.7.3 IK分词器安装

  1. 下载 IK 分词器压缩包;

    注意:IK分词器下载地址ES和IK的版本对应

  2. 将IK分词器解压后上传至服务器,并改名字为ik;

  3. 将ik目录拷贝到Docker容器的plugins目录下。

    docker cp ./ik elasticsearch:/usr/share/elasticsearch/plugins
    


2.7.4 IK分词器测试

POST http://192.168.31.35:9200/_analyze

注意:这里使用的是6.7.1版本的,不同版本之间的方式不一样。

  • ik_smart:会做最粗粒度的拆分;

    携带参数如下:

    {
        "analyzer": "ik_smart",
        "text": "我是程序员"
    }
    

  • ik_max_word:会将文本做最细粒度的拆分。

    携带参数如下:

    {
        "analyzer": "ik_max_word",
        "text": "我是程序员"
    }
    



2.8 Kibana

2.8.1 Kibana概念

    Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 ElasticSearch 协作。您可以使用 Kibana 对 ElasticSearch 索引中的数据进行搜索、查看、交互操作。您可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现。

    Kibana 可以使大数据通俗易懂。它很简单,基于浏览器的界面便于您快速创建和分享动态数据仪表板来追踪 ElasticSearch 的实时数据变化。搭建 Kibana 非常简单。您可以分分钟完成 Kibana 的安装并开始探索 Elasticsearch 的索引数据 — 没有代码、不需要额外的基础设施。


2.8.2 Kibana安装

这里以Docker创建Kibana容器为例。

  1. 拉取Kibana镜像;

    docker pull docker.io/kibana:6.7.1
    

    注意:Kibana的版本。

  2. 创建并运行Kibana容器。

    docker run -d -e ELASTICSEARCH_URL=http://192.168.31.35:9200 --name kibana --restart=always -p 5601:5601 kibana:6.7.1
    
  3. 如果启动失败,检查kibana.yml文件。

    docker exec -it kibana /bin/bash
    cd config
    vi kivana.yml
    
    elasticsearch.hosts: [ "http://192.168.31.35:9200" ]#修改elasticsearch.hosts的值为自己的es的ip
    



2.8.3 Kibana使用

2.8.3.1 配置索引

        要使用Kibana,您必须至少配置一个索引。索引用于标识 Elasticearch 索引以运行搜索和分析。它们还用于配置字段。


2.8.3.2数据搜索

        Discover为数据搜索部分,可以对日志信息进行搜索操作。可以使用Discover实现数据搜索过滤和搜索条件显示以及关键词搜索,如下图:


2.8.3.3 数据可视化


2.8.3.4 控制台操作数据



2.8.4 使用DSL语句

2.8.4.1 Query DSL结构化查询

    Query DSL是一个 Java 开源框架用于构建类型安全的 SQL 查询语句。采用 API 代替传统的拼接字符串来构造查询语句。目前,Querydsl支持的平台包括JPA、JDO、SQL、Java Collections、RDF、Lucene、Hibernate Search。ElasticSearch 提供了一整套基于JSON 的 DSL 语言来定义查询。


2.8.4.2 常用快捷键

ctrl+i #自动缩进
ctrl+enter #提交请求
down #打开自动补全菜单
enter或tab #选中项自动补全
esc #关闭补全菜单

2.8.4.3 索引操作

  1. 查询所有索引;

    GET /_cat/indices?v
    

  2. 新增索引;

    PUT /user
    

    注意:从7.0.0版本开始,默认只有一个分片,而不是5个了,所以如果想要多个分片需要在创建索引的时候指定。

  3. 删除某个索引;

    DELETE /user
    

  4. 创建映射;

    PUT /user/userinfo/_mapping
    {
      "properties": {
        "name": {
          "type": "text",
          "analyzer": "ik_smart",
          "search_analyzer": "ik_smart"
        },
        "city": {
          "type": "text",
          "analyzer": "ik_smart",
          "search_analyzer": "ik_smart"
        },
        "age": {
          "type": "long"
        },
        "description": {
          "type": "text",
          "analyzer": "ik_smart",
          "search_analyzer": "ik_smart"
        }
      }
    }
    

    为什么要删除映射类型?各版本之间语句的使用有什么区别?


2.8.4.4 数据操作

  1. 新增文档数据;

    PUT /user/userinfo/1
    {
      "name": "李四",
      "age": 22,
      "city": "深圳",
      "description": "李四来自湖北武汉!"
    }
    
    PUT /user/userinfo/2
    {
      "name": "王五",
      "age": 35,
      "city": "深圳",
      "description": "王五家住在深圳!"
    }
    
    PUT /user/userinfo/3
    {
      "name": "张三",
      "age": 19,
      "city": "深圳",
      "description": "在深圳打工,来自湖北武汉"
    } 
    
    PUT /user/userinfo/4
    {
      "name": "张三丰",
      "age": 66,
      "city": "武汉",
      "description": "在武汉读书,家在武汉!"
    } 
    
    PUT /user/userinfo/5
    {
      "name": "赵子龙",
      "age": 77,
      "city": "广州",
      "description": "赵子龙来自深圳宝安,但是在广州工作!",
      "address": "广东省茂名市"
    } 
    
    PUT /user/userinfo/6
    {
      "name": "赵毅",
      "age": 55,
      "city": "广州",
      "description": "赵毅来自广州白云区,从事电子商务8年!"
    } 
    
    PUT /user/userinfo/7
    {
      "name": "赵哈哈",
      "age": 57,
      "city": "武汉",
      "description": "武汉赵哈哈,在深圳打工已有半年了,月薪7500!"
    }
    

    注意:更新数据也可以使用新增操作,这种操作会将整个数据替换掉。

  2. 修改文档数据;

    使用POST更新某个列的数据。

    POST /user/userinfo/4/_update
    {
      "doc": {
        "name": "张三丰",
        "description": "在武汉读书,家在武汉!在深圳工作!"
      }
    }
    

  3. 根据id查询,获取文档数据;

    GET /user/userinfo/4
    

  4. 查询索引下的全部文档数据;

    GET /user/_search
    

    查询全部索引的全部文档数据:GET _search

  5. 排序查询文档数据;

    GET /user/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": {
        "age": {
          "order": "desc"
        }
      }
    }
    

  6. 分页查询文档数据;

    GET /user/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": {
        "age": {
          "order": "desc"
        }
      },
      "from": 0,
      "size": 2
    }
    
    • from:从下N的记录开始查询;
    • size:每页显示条数。

  7. 删除文档数据;

    DELETE user/userinfo/7
    

2.8.4.5 查询模式

  1. term查询;

    term主要用于精确匹配(不分词),如字符串、数值、日期等。

    不适合情况:1.列中除英文字符外有其它值 ;2.字符串值中有冒号或中文 ;3.系统自带属性如_version。

    GET _search
    {
      "query": {
        "term": {
          "city": "武汉"
        }
      }
    }
    

  2. terms查询;

    terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配。

    GET _search
    {
      "query": {
        "terms": {
          "city": [
            "武汉",
            "广州"
          ]
        }
      }
    }
    

  3. match查询;

    与term查询不同的是,match查询会使用映射中设置的分词器,对搜索值进行分词后再匹配查询

    GET _search
    {
      "query": {
        "match": {
          "city": "广州武汉"
        }
      }
    }
    

  4. query_string查询;

    默认使用空格拆分成多个子项,并且每个子项都会去分词查询。可以通过 default_operator 指定子项之间的关系,默认是或 。match 查询只是分词以后查询,相当于 query_string 用空格隔开的一个个子项查询,query_string查询相当于match查询的增强版。

    GET _search
    {
        "query": {
            "query_string": {
                "default_field": "city",
                "query": "广州武汉"
            }
        }
    }
    

    query_string 和 match有什么区别?

  5. range 查询;

    range过滤允许我们按照指定范围查找一批数据,例如查询年龄范围。

    GET _search
    {
      "query": {
        "range": {
          "age": {
            "gte": 30,
            "lte": 57
          }
        }
      }
    }
    

  6. exists查询;

    exists 过滤可以用于查找拥有某个域的数据

    GET _search
    {
      "query": {
        "exists": {
          "field": "address"
        }
      }
    }
    

  7. bool 查询;

    bool 查询可以用来合并多个条件查询结果的布尔逻辑,它包含一下操作符:

    • must : 多个查询条件的完全匹配,相当于 and。
    • must_not : 多个查询条件的相反匹配,相当于 not。
    • should : 至少有一个查询条件匹配, 相当于 or。
    GET _search
    {
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "city": {
                  "value": "深圳"
                }
              }
            },
            {
              "range": {
                "age": {
                  "gte": 20,
                  "lte": 99
                }
              }
            }
          ]
        }
      }
    }
    

  8. match_all 查询;

    可以查询到所有文档,是没有查询条件下的默认语句。

    前面已经用了很多次了,这里就不介绍了。

  9. prefix 查询;

    以什么字符开头的,可以更简单地用 prefix ,例如查询所有以张开始的用户描述。

    GET _search
    {
      "query": {
        "prefix": {
          "name": {
            "value": "张"
          }
        }
      }
    }
    

  10. multi_match 查询。

    multi_match查询允许你做match查询的基础上同时搜索多个字段,在多个字段中同时查一个

    GET _search
    {
      "query": {
        "multi_match": {
          "query": "深圳",
          "fields": [
            "city",
            "description"
          ]
        }
      }
    }
    

  11. filter查询。

    在查询前添加过滤条件后再进行查询。尽量使用过滤代替查询,因为多次过滤可以使用缓存,而且过滤不需要计算分数,从性能上来说过滤更好

    注意:一般使用查询(query)来进行==全文搜索或其它任何需要影响相关性得分==的搜索。除此以外的情况都使用过滤(filters) 。

    GET _search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match_all":{}
            }
          ], 
          "filter": {
            "range": {
                "age": {
                  "gte": 30,
                  "lte": 57
                }
              }
          }
        }
      }
    }
    

2.8.5 ElasticSearch原生API编程

2.8.5.1 POM文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lijinghua</groupId>
    <artifactId>es-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            以上是关于全文检索-ElasticSearch入门的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch全文检索技术 一篇文章即可从入门到精通(Elasticsearch安装,安装kibana,安装ik分词器,数据的增删改查,全文检索查询,聚合aggregations)(代码片

全文搜索引擎 Elasticsearch 入门教程

全文搜索引擎 Elasticsearch 入门教程

全文搜索引擎 Elasticsearch 入门教程

Elasticsearch全文检索工具入门

大数据全文搜索引擎 Elasticsearch 入门教程