zoukankan      html  css  js  c++  java
  • Elastic Search 介绍及入门

    什么是全文搜索引擎?

    数据的分类

    • 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。对于结构化数据,我们一般都是可以通过关系型数据库(mysql,oracle等)的 table 的方式存储和搜索,也可以建立索引。通过b-tree等数据结构快速搜索数据。
    • 非结构化数据:全文数据,指不定长或无固定格式的数据,如邮件,word文档等。对于非结构化数据,也即对全文数据的搜索主要有两种方法:顺序扫描法,全文搜索法。

    顺序扫描

    • 按字面意思,我们可以了解它的大概搜索方式,就是按照顺序扫描的方式查找特定的关键字。比如让你在一篇篮球新闻中,找出"科比"这个名字在哪些段落出现过。那你肯定需要从头到尾把文章阅读一遍,然后标记出关键字在哪些地方出现过。
    • 这种方法毋庸置疑是最低效的,如果文章很长,有几万字,等你阅读完这篇新闻找到"科比"这个关键字,那得花多少时间。

    全文搜索

    • 对非结构化数据进行顺序扫描很慢,我们是否可以进行优化?把我们的非结构化数据想办法弄得有一定结构不就行了吗?将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对这些有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这种方式就构成了全文搜索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
    • 我们以NBA中国网站为例,假设我们都是篮球爱好者,并且我们是科密,那如何快速找到有关科比的新闻呢?全文搜索的方式就是,将所有新闻中所有的关键字进行提取,比如"科比","詹姆斯","总冠军","MVP"等关键字,然后对这些关键字建立索引,通过索引我们就可以找到对应的该关键词出现的新闻了。

    什么是全文搜索引擎

    根据百度百科中的定义,全文搜索引擎是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的。

    搜索引擎

    • Lucene
    • Solr
    • Elastic search

    为什么不用mysql做全文搜索

    有人可能会问,为什么一定要用搜索引擎呢?我们的所有数据不是都可以放在数据库里吗?而且 Mysql,Oracle,SQL Server 等数据库里不是也能提供查询搜索功能,直接通过数据库查询不就可以了吗?

    确实,我们大部分的查询功能都可以通过数据库查询获得,如果查询效率低下,还可以通过新建数据库索引,优化SQL等方式进行提升效率,甚至通过引入缓存比如 redis,memcache 来加快数据的返回速度。如果数据量更大,还可以通过分库分表来分担查询压力。

    那为什么还要全文搜索引擎呢?我们从几个角度来说

    数据类型

    • 全文索引搜索很好的支持非结构化数据的搜索,可以更好地快速搜索大量存在的任何单词非结构化文本。例如 Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。

    搜索性能

    • 如果使用mysql做搜索,比如有个player表,这个表有user_name这个字段,我们要查找出user_name以james开头的球员,和含有James的球员。我们一般怎么做?数据量达到千万级别的时候怎么办?

    灵活的搜索

    • 如果我们想查出名字叫james的球员,但是用户输入了jame,我们想提示他一些关键字
    • 如果我们想查出带有"冠军"关键字的文章,但是用户输入了"总冠军",我们也希望能查出来。

    索引的维护

    • 一般传统数据库,全文搜索都实现的很鸡肋,因为一般也没人用数据库存长文本字段,因为进行全文搜索的时候需要扫描整个表,如果数据量大的话即使对SQL的语法进行优化,也是效果甚微。即使建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。

    适合全文索引引擎的场景

    • 搜索的数据对象是大量的非结构化的文本数据。
    • 文本数据量达到数十万或数百万级别,甚至更多。
    • 支持大量基于交互式文本的查询。
    • 需求非常灵活的全文搜索查询。
    • 对安全事务,非文本数据操作的需求相对较少的情况。

    常见的搜索引擎

    Lucene

    • Lucene 是一个Java全文搜索引擎,完全用Java编写。Lucene不是一个完整的应用程序,而是一个代码库和API,可以很容易地用于向应用程序添加搜索功能。
    • 通过简单的API提供强大的功能
      • 可扩展的高性能索引
      • 强大,准确,高效的搜索算法
      • 跨平台解决方案
    • Apache软件基金会
      • 在Apache软件基金会提供的开源软件项目的Apache社区的支持。
      • 但是Lucene只是一个框架,要充分利用它的功能,需要使用java,并且在程序中集成Lucene。需要很多的学习了解,才能明白它是如何运行的,熟练运用Lucene确实非常复杂。

    Solr

    • Solr是一个基于Lucene的Java库构建的开源搜索平台。它以用户友好的方式提供Apache Lucene的搜索功能。它是一个成熟的产品,拥有强大而广泛的用户社区。它能提供分布式索引,复制,负载均衡查询以及自动故障转移和恢复。如果它被正确部署然后管理得好,它就能够成为一个高度可靠,可扩展且容错的搜索引擎。很多互联网巨头,如Netflix,eBay,Instagram和亚马逊都使用Solr,因为它能够索引和搜索多个站点。
    • 强大的功能
      • 全文搜索
      • 突出
      • 分面搜索
      • 实时索引
      • 动态群集
      • 数据库集成
      • NoSQL功能和丰富的文档处理

    Elasticsearch

    • Elasticsearch 是一个开源,是一个基于Apache Lucene库构建的Restful搜索引擎.
    • Elasticsearch 是在Solr之后几年推出的。它提供了一个分布式,多租户能力的全文搜索引擎,具有HTTP Web界面(REST)和无架构JSON文档。Elasticsearch的官方客户端库提供Java,Groovy,PHP,Ruby,Perl,Python,.NET和Javascript。
    • 主要功能
      • 分布式搜索
      • 数据分析
      • 分组和聚合
    • 应用场景
      • 维基百科
      • Stack Overflow
      • GitHub
      • 电商网站
      • 日志数据分析
      • 商品价格监控网站
      • BI系统
      • 站内搜索
      • 篮球论坛

    Elastic Search 核心概念的介绍

    我们在学习 elastic search 的核心概念之前,回顾下我们使用传统数据库查询数据的时候应该怎么做的?假设我们用使用mysql数据库存储一些数据,我们的操作步骤是怎样的?

    建立数据库->建表->插入数据->查询

    我们用mysql的概念类比 elastic search 的概念

    索引(index)

    • 一个索引可以理解成一个关系型数据库。

    类型(type)

    • 一种type就像一类表,比如user表,order表。
    • ES 5.x中一个index可以有多种type。
    • ES 6.x中一个index只能有一种type。
    • ES 7.x以后已经移除type这个概念。

    映射(mapping)

    • mapping定义了每个字段的类型等信息。相当于关系型数据库中的表结构。

    文档(document)

    • 一个document相当于关系型数据库中的一行记录。

    字段(field)

    • 相当于关系型数据库表的字段

    集群(cluster)

    • 集群由一个或多个节点组成,一个集群有一个默认名称"elasticsearch"。

    节点(node)

    • 集群的节点,一台机器或者一个进程

    分片和副本(shard)

    • 副本是分片的副本。分片有主分片(primary Shard)和副本分片(replica Shard)之分。一个Index数据在物理上被分布在多个主分片中,每个主分片只存放部分数据。每个主分片可以有多个副本,叫副本分片,是主分片的复制。

    Elasticsearch 使用 Restful 风格 api 来设计的

    • HEAD:只获取某个资源的头部信息
    • GET:获取资源
    • POST:创建或更新资源
    • PUT:创建或更新资源
    • DELETE:删除资源

    索引的介绍和使用

    • 新增索引(使用 PUT 请求):localhost:9200/索引名称
    • 获取索引(使用 GET 请求):localhost:9200/索引名称
    • 删除索引(使用 DELETE 请求):localhost:9200/索引名称
    • 批量获取索引(使用 GET请求):localhost:9200/索引名称1,索引名称2
    • 获取所有索引(使用 GET请求):关闭索引(使用 POST 请求):localhost:9200/索引名称/_close
      • localhost:9200/_all
      • localhost:9200/_cat/indices?v
    • 开启索引(使用 POST 请求):localhost:9200/索引名称/_open
    • 判断索引是否存在(使用 HEAD 请求):localhost:9200/索引名称

     

     

     

     

    映射的介绍和使用

    • 新增 mapping(使用 PUT 请求):localhost:9200/索引名称/_mapping       注意:没有删除和修改原本就有的mapping的功能
    • 获取 mapping(使用 GET 请求):localhost:9200/索引名称/_mapping
    • 批量获取 mapping(使用 GET 请求):localhost:9200/索引名称1,索引名称2/_mapping
    • 获取所有 mapping(使用 GET 请求):
      • localhost:9200/_mapping
      • localhost:9200/_all/_mapping

    {
        "properties":{
            "name":{
                "type":"text"
            },
            "team_name":{
                "type":"text"
            },
            "position":{
                "type":"keyword"
            },
            "play_year":{
                "type":"keyword"
            },
            "jerse_no":{
                "type":"keyword"
            }
        }
    }

     

    文档的增删改查

    1)新增文档(指定id)

    (使用 PUT 请求):localhost:9200/索引名称/_doc/id

    2)新增文档(不指定id)

    (使用 POST 请求):localhost:9200/索引名称/_doc   注意:不指定id,会生成随机id

    3)自动创建索引

    • 查看 auto_create_index 开关状态,请求 http://localhost:9200/_cluster/settings
    • 当索引不存在并且 auto_create_index 为 true 的时候,新增文档时会自动创建索引
    • 修改 auto_create_index 状态
      • PUT localhost:9200/_cluster/settings
      • {
            "persistent":{
                "action.auto_create_index":"false"
            }
        }
    • 当 auto_create_index=false 时,指定一个不存在的索引,新增文档
      • (使用 PUT 请求):localhost:9200/不存在的索引名称/_doc/id

    4)指定操作类型

    (使用 PUT 请求):localhost:9200/索引名称/_doc/id?op_type=create

    如果不指定类型,那么就会修改原本存在的文档

     

    5)查看文档

    (使用 GET 请求):localhost:9200/索引名称/_doc/id

    查看多个文档

    (使用 POST 请求):localhost:9200/_mget

    {
        "docs":[
            {
                "_index":"nba",
                "_type":"_doc",
                "_id":"1"
            },
            {
                "_index":"nba",
                "_type":"_doc",
                "_id":"2"
            }
        ]
    }

    (使用 POST 请求):localhost:9200/索引名称/_mget

    (使用 POST 请求):localhost:9200/索引名称/_doc/_mget

    POST localhost:9200/nba/_mget
    
    参数:
    {
        "docs":[
            {
                "_type":"_doc",
                "_id":"1"
            },
            {
                "_type":"_doc",
                "_id":"2"
            }
        ]
    }
    
    
    POST localhost:9200/nba/doc/mget
    
    参数1
    {
        "docs":[
            {
                "_id":"1"
            },
            {
                "_id":"2"
            }
        ]
    }
    
    参数2
    {
        "ids" : ["1", "2"]
    }

    6)修改文档

    根据提供的文档片段更新数据

    (使用 POST 请求):localhost:9200/索引名称/_update/id

    POST localhost:9200/nba/_update/1
    
    参数:
    {
        "doc":{
            "name":"哈登",
            "team_name":"⽕火箭",
            "position":"双能卫",
            "play_year":"10",
            "jerse_no":"13"
        }
    }

    向_source字段,增加一个字段

    (使用 POST 请求):localhost:9200/索引名称/_update/id

    POST localhost:9200/nba/_update/1
    
    参数:
    {
        "script":"ctx._source.age = 18"
    }

     

    从_source字段,删除一个字段

    (使用 POST 请求):localhost:9200/索引名称/_update/id

    POST localhost:9200/nba/_update/1
    
    参数:
    {
        "script":"ctx._source.remove("age")"
    }

    根据参数值,更新指定文档的字段

    (使用 POST 请求):localhost:9200/索引名称/_update/id

    POST localhost:9200/nba/_update/1
    
    参数:
    {
        "script":{
            "source":"ctx._source.age += params.age",
            "params":{
                "age":4
            }
        }
    }

    upsert 当指定的文档不存在时,upsert参数包含的内容将会被插入到索引中,作为一个新文档;如果指定的文档存在,ElasticSearch 引擎将会执行指定的更新逻辑。

    (使用 POST 请求):localhost:9200/索引名称/_update/id

    POST localhost:9200/nba/_update/1
    
    参数:
    {
        "script":{
            "source":"ctx._source.allstar += params.allstar",
            "params":{
                "allstar":4
            }
        },
        "upsert":{
            "allstar":1
        }
    }

    7)删除文档

    (使用 DELETE 请求):localhost:9200/索引名称/_doc/id

  • 相关阅读:
    线性最大子数组的求法(二)
    高难度智力题
    职业规划
    良好的学习习惯
    毕业生面试绝招
    编写Java程序最容易犯的21种错误
    spring02
    spring_01
    用soapUI生成客户端代码
    idea创建git分支
  • 原文地址:https://www.cnblogs.com/jwen1994/p/12390407.html
Copyright © 2011-2022 走看看