zoukankan      html  css  js  c++  java
  • Elasticsearch常见用法-入门

    1. 前台启动
      默认是只有本地可以访问
    ./bin/elasticsearch
    
    1. 远程访问

    修改elasticsearch.yml,把network.host(注意配置文件格式不是以 # 开头的要空一格, :后要空一格)
    network.host: 0.0.0.0

    1. 在后台以守护进程模式运行

    添加 -d 参数

    ./bin/elasticsearch -d
    
    1. 查看状态
    curl 'http://localhost:9200/?pretty'
    
    {
      "name": "node-1",
      "cluster_name": "my-application",
      "cluster_uuid": "x6eQJV6nR6SLjm3cvqSJ6A",
      "version": {
        "number": "7.5.0",
        "build_flavor": "default",
        "build_type": "tar",
        "build_hash": "e9ccaed468e2fac2275a3761849cbee64b39519f",
        "build_date": "2019-11-26T01:06:52.518245Z",
        "build_snapshot": false,
        "lucene_version": "8.3.0",
        "minimum_wire_compatibility_version": "6.8.0",
        "minimum_index_compatibility_version": "6.0.0-beta1"
      },
      "tagline": "You Know, for Search"
    }
    
    1. 集群和节点

    节点(node)是一个运行着的Elasticsearch实例。集群(cluster)是一组具有相同 cluster.name 的节点集合,他们协同工作,共享数据并提供故障转移和扩展功能,当然一个节点也可以组成一个集群。可以通过修改 config/ 目录下的 elasticsearch.yml 文件,然后启ELasticsearch来做到这一点。

    1. 关闭ES
      当Elasticsearch在前台运行,可以使用 Ctrl-C 快捷键终止,或者你可以调
      shutdown API来关闭:
    curl -XPOST 'http://localhost:9200/_shutdown'
    
    1. 与Elasticsearch交互
      如何与Elasticsearch交互取决于你是否使用Java。
    • Java API
      Elasticsearch为Java用户提供了两种内置客户端:
      • 节点客户端(node client):
        节点客户端以无数据节点(none data node)身份加入集群,换言之,它自己不存储任何数据,但是它知道数据在集群中的具体位置,并且能够直接转发请求到对应的节点上。
      • 传输客户端(Transport client):这个更轻量的传输客户端能够发送请求到远程集群。它自己不加入集群,只是简单转发请求给集群中的节点。
        两个Java客户端都通过9300端口与集群交互,使用Elasticsearch传输协议(Elasticsearch Transport Protocol)。集群中的节点之间也通过9300端口进行通信。如果此端口未开放,你的节点将不能组成集群。

    TIP
    Java客户端所在的Elasticsearch版本必须与集群中其他节点一致,否则,它们可能互相
    无法识别。

    • 基于HTTP协议,以JSON为数据交互格式的RESTful API
      其他所有程序语言都可以使用RESTful API,通过9200端口的与Elasticsearch进行通信,你可以使用你喜欢的WEB客户端,事实上,如你所见,你甚至可以通过 curl 命令与Elasticsearch通信。

    向Elasticsearch发出的请求的组成部分与其它普通的HTTP请求是一样的:
    curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

    VERB: HTTP方法: GET , POST , PUT , HEAD , DELETE
    PROTOCOL: http或者https协议(只有在Elasticsearch前面有https代理的时候可用)
    HOST: Elasticsearch集群中的任何一个节点的主机名,如果是在本地的节点,那么就叫localhost
    PORT: Elasticsearch HTTP服务所在的端口,默认为9200
    PATH: API路径(例如_count将返回集群中文档的数量),PATH可以包含多个组件,例如_cluster/stats或者_nodes/stats/jvm
    QUERY_STRING: 一些可选的查询请求参数,例如 ?pretty 参数将使请求返回更加美观易读的JSON数据
    BODY: 一个JSON格式的请求主体(如果请求需要的话)

    举例说明,为了计算集群中的文档数量,我们可以这样做:

    curl -XGET 'http://localhost:9200/_count?pretty' -d '
    {
      "query": {
        "match_all": {}
      }
    }'
    

    Elasticsearch返回一个类似 200 OK 的HTTP状态码和JSON格式的响应主体(除了 HEAD 请求)。上面的请求会得到如下的JSON格式的响应主体:

    {
      "count" : 5507,
      "_shards" : {
        "total" : 9,
        "successful" : 9,
        "skipped" : 0,
        "failed" : 0
      }
    }
    

    我们看不到HTTP头是因为我们没有让 curl 显示它们,如果要显示,使用 curl 命令后跟 -i 参数:

    curl -i -XGET 'localhost:9200/'
    

    以后将简写 curl 请求中重复的部分,例如主机名和端口,还有 curl 命令本身。
    一个完整的请求形如:

    curl -XGET 'http://localhost:9200/_count?pretty' -d '
    {
      "query": {
        "match_all": {}
      }
    }'
    

    将简写成这样:

    GET /_count
    {
      "query": {
        "match_all": {}
      }
    }
    
    1. 在Elasticsearch中存储数据的行为就叫做索引(indexing),在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中。对比图来类比传统关系型数据库:
    Relational DB -> Databases -> Tables -> Rows -> Columns
    Elasticsearch -> Indices -> Types -> Documents -> Fields
    

    Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。
    (新版本中每一个索引只能包含一种类型)

    索引含义的区分

    • 索引(名词) 一个索引(index)就像是传统关系数据库中的数据库,它是相关文档存储的地方,index的复数是indices 或indexes。
    • 索引(动词) 「索引一个文档」表示把一个文档存储到索引(名词)里,以便它可以被检索或者查询。这很像SQL中的 INSERT 关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。
    • 倒排索引 传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。Elasticsearch和Lucene使用一种叫做倒排索引(inverted index)的数据结构来达到相同目的。

    默认情况下,文档中的所有字段都会被索引(拥有一个倒排索引),只有这样他们才是可被搜索的。

    1. 添加索引数据
    PUT /megacorp/_doc/1
    {
        "first_name" : "John",
        "last_name" : "Smith",
        "age" : 25,
        "about" : "I love to go rock climbing",
        "interests": [ "sports", "music" ]
    }
    

    返回结果:

    {
      "_index" : "megacorp",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 1,
      "result" : "create",
      "_shards" : {
        "total" : 2,
        "successful" : 1,
        "failed" : 0
      },
      "_seq_no" : 4,
      "_primary_term" : 1
    }
    
    
    1. 检索文档
      执行HTTP GET请求并指出文档的“地址”——索引、类型和ID既可。根据这三部分信息,我们就可以返回原始JSON文档:
    GET /megacorp/_doc/1
    

    响应的内容中包含一些文档的元信息,John Smith的原始JSON文档包含在 _source 字段中。

    {
      "_index" : "megacorp",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 1,
      "_seq_no" : 0,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "first_name" : "John",
        "last_name" : "Smith",
        "age" : 25,
        "about" : "I love to go rock climbing",
        "interests" : [
          "sports",
          "music"
        ]
      }
    }
    

    通过HTTP方法 GET 来检索文档,同样的,可以使用 DELETE 方法删除文档,使用 HEAD 方法检查某文档是否存在。如果想更新已存在的文档,只需再 PUT 一次。

    1. 简单搜索
      尝试一个最简单的搜索全部员工的请求:
    GET /megacorp/_search
    
    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 4,
          "relation" : "eq"
        },
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "first_name" : "John",
              "last_name" : "Smith",
              "age" : 25,
              "about" : "I love to go rock climbing",
              "interests" : [
                "sports",
                "music"
              ]
            }
          },
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "3",
            "_score" : 1.0,
            "_source" : {
              "first_name" : "Jane",
              "last_name" : "Smith",
              "age" : 32,
              "about" : "I like to collect rock albums",
              "interests" : [
                "music"
              ]
            }
          },
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "4",
            "_score" : 1.0,
            "_source" : {
              "first_name" : "Douglas",
              "last_name" : "Fir",
              "age" : 35,
              "about" : "I like to build cabinets",
              "interests" : [
                "forestry"
              ]
            }
          },
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "2",
            "_score" : 1.0,
            "_source" : {
              "first_name" : "John",
              "last_name" : "Smith",
              "age" : 25,
              "about" : "I love to go rock climbing",
              "interests" : [
                "sports",
                "music"
              ]
            }
          }
        ]
      }
    }
    
    

    在结尾使用关键字 _search 来取代原来的文档ID。响应内容的 hits 数组中包含了我们所有的四个文档。
    默认情况下搜索会返回前10个结果。

    注意:响应内容不仅会告诉我们哪些文档被匹配到,而且这些文档内容完整的被包含在其中

    搜索姓氏中包含“Smith”的员工。要做到这一点,我们将在命令行中使用轻量级的搜索方法。这种方法常被称作查询字符串(query string)搜索,因为我们像传递URL参数一样去传递查询语句:

    GET /megacorp/_search?q=last_name:Smith
    

    在请求中依旧使用 _search 关键字,然后将查询语句传递给参数 q= 。这样就可以得到所有姓氏为Smith的结果:

    1. 使用DSL语句查询
      查询字符串搜索便于通过命令行完成特定(ad hoc)的搜索。Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。
      DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。我们可以这样表示之前关于“Smith”的查询:
    GET /megacorp/_search
    {
      "query": {
        "match": {
          "last_name": "Smith"
        }
      }
    }
    

    这会返回与之前查询相同的结果。不再使用查询字符串(query string)做为参数,而是使用请求体代替。这个请求体使用JSON表示,其中使用了 match 语句

    1. 更复杂的搜索
      添加过滤器(filter)
    # 之前的语法
    GET /megacorp/_search
    {
        "query" : {
            "filtered" : {
                "filter" : {
                    "range" : {
                        "age" : { "gt" : 30 } <1>
                    }
                },
                "query" : {
                    "match" : {
                        "last_name" : "smith" <2>
                    }
                }
            }
        }
    }
    
    # 现在的语法
    GET /megacorp/_search
    {
      "query": {
        "bool": {
          "filter": {
            "range": {
              "age": {
                "gt": 30
              }
            }
          },
          "must": [
            {"match": {
              "last_name": "smith"
            }}
          ]
        }
      }
    }
    
    1. 全文搜索
      搜索所有喜欢“rock climbing”的员工:
      match是把短语拆分开,一个词一个词的查询
    GET /megacorp/_search
    {
      "query": {
        "match": {
          "about": "rock climbing"
        }
      }
    }
    

    可以看到我们使用了之前的 match 查询,从 about 字段中搜索"rock climbing",我们得到了两个匹配文档:

    {
      "took" : 16,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 3,
          "relation" : "eq"
        },
        "max_score" : 1.0314757,
        "hits" : [
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "1",
            "_score" : 1.0314757,
            "_source" : {
              "first_name" : "John",
              "last_name" : "Smith",
              "age" : 25,
              "about" : "I love to go rock climbing",
              "interests" : [
                "sports",
                "music"
              ]
            }
          },
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "2",
            "_score" : 1.0314757,
            "_source" : {
              "first_name" : "John",
              "last_name" : "Smith",
              "age" : 25,
              "about" : "I love to go rock climbing",
              "interests" : [
                "sports",
                "music"
              ]
            }
          },
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "3",
            "_score" : 0.35044178,
            "_source" : {
              "first_name" : "Jane",
              "last_name" : "Smith",
              "age" : 32,
              "about" : "I like to collect rock albums",
              "interests" : [
                "music"
              ]
            }
          }
        ]
      }
    }
    
    

    默认情况下,Elasticsearch根据结果相关性评分来对结果集进行排序,所谓的「结果相关性评分」就是文档与查询条件的匹配程度。很显然,排名第一的 John Smith 的 about 字段明确的写到“rock climbing”。
    但是为什么 Jane Smith 也会出现在结果里呢?原因是“rock”在她的 abuot 字段中被提及了。因为只有“rock”被提及而“climbing”没有,所以她的 _score 要低于John。

    这个例子很好的解释了Elasticsearch如何在各种文本字段中进行全文搜索,并且返回相关性最大的结果集。

    1. 短语搜索
      也就是说把查询条件作为一个整体来查询,不拆开进行查询。将 match 查询变更为 match_phrase 查询即可:
    GET /megacorp/_search
    {
      "query": {
        "match_phrase": {
          "about": "rock climbing"
        }
      }
    }
    

    毫无疑问,该查询返回John Smith的文档:

    {
      "took" : 19,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 2,
          "relation" : "eq"
        },
        "max_score" : 1.0314757,
        "hits" : [
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "1",
            "_score" : 1.0314757,
            "_source" : {
              "first_name" : "John",
              "last_name" : "Smith",
              "age" : 25,
              "about" : "I love to go rock climbing",
              "interests" : [
                "sports",
                "music"
              ]
            }
          },
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "2",
            "_score" : 1.0314757,
            "_source" : {
              "first_name" : "John",
              "last_name" : "Smith",
              "age" : 25,
              "about" : "I love to go rock climbing",
              "interests" : [
                "sports",
                "music"
              ]
            }
          }
        ]
      }
    }
    
    
    1. 高亮搜索
      很多应用喜欢从每个搜索结果中高亮(highlight)匹配到的关键字,这样用户可以知道为什么这些文档和查询相匹配。在Elasticsearch中高亮片段是非常容易的。
      在之前的语句上增加 highlight 参数:
    GET /megacorp/_search
    {
      "query": {
        "match_phrase": {
          "about": "rock climbing"
        }
      },
      "highlight": {
        "fields": {
          "about": {}
        }
      }
    }
    

    在返回结果中会有一个新的部分叫做 highlight ,这里包含了来自 about 字段中的文本,并且用 <em></em> 来标识匹配到的单词。

    {
      "took" : 112,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 2,
          "relation" : "eq"
        },
        "max_score" : 1.0314757,
        "hits" : [
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "1",
            "_score" : 1.0314757,
            "_source" : {
              "first_name" : "John",
              "last_name" : "Smith",
              "age" : 25,
              "about" : "I love to go rock climbing",
              "interests" : [
                "sports",
                "music"
              ]
            },
            "highlight" : {
              "about" : [
                "I love to go <em>rock</em> <em>climbing</em>"
              ]
            }
          },
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "2",
            "_score" : 1.0314757,
            "_source" : {
              "first_name" : "John",
              "last_name" : "Smith",
              "age" : 25,
              "about" : "I love to go rock climbing",
              "interests" : [
                "sports",
                "music"
              ]
            },
            "highlight" : {
              "about" : [
                "I love to go <em>rock</em> <em>climbing</em>"
              ]
            }
          }
        ]
      }
    }
    
    
    1. 分析-聚合
      Elasticsearch有一个功能叫做聚合(aggregations),它允许你在数据上生成复杂的分析统计。它很像SQL中的 GROUP BY 但是功能更强大。

    老版本用法如下:

    GET /megacorp/_search
    {
      "aggs": {
    
        "all_interests": {
          "terms": {
            "field": "interests"
          }
        }
      }
    }
    

    如果使用的是Elasticsearch 5版本以上的话,将会出现如下异常:

    {
      "error": {
        "root_cause": [
          {
            "type": "illegal_argument_exception",
            "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
          }
        ],
        "type": "search_phase_execution_exception",
        "reason": "all shards failed",
        "phase": "query",
        "grouped": true,
        "failed_shards": [
          {
            "shard": 0,
            "index": "megacorp",
            "node": "PiLgJiUqTHmF-CtvlliYVA",
            "reason": {
              "type": "illegal_argument_exception",
              "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
            }
          }
        ],
        "caused_by": {
          "type": "illegal_argument_exception",
          "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead.",
          "caused_by": {
            "type": "illegal_argument_exception",
            "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
          }
        }
      },
      "status": 400
    }
    

    大概的意思是:Fielddata可以消耗大量的堆空间,特别是在加载高基数文本字段时。一旦fielddata已经加载到堆中,它在该段的生存期内保持。此外,加载fielddata是一个昂贵的过程,可以导致用户体验延迟命中。
    所以fielddata默认禁用。如果尝试对文本字段上的脚本进行排序,聚合或访问值,就会看到这个异常,具体使用可以参考手册。

    1. 分布式
      Elasticsearch致力于隐藏分布式系统的复杂性。以下这些操作都是在底层自动完成的:
    • 将你的文档分区到不同的容器或者分片(shards)中,它们可以存在于一个或多个节点中。
    • 将分片均匀的分配到各个节点,对索引和搜索做负载均衡。
    • 冗余每一个分片,防止硬件故障造成的数据丢失。
    • 将集群中任意一个节点上的请求路由到相应数据所在的节点。
    • 无论是增加节点,还是移除节点,分片都可以做到无缝的扩展和迁移。
  • 相关阅读:
    【LeetCode-链表】环形链表
    【LeetCode-数学】快乐数
    【LeetCode-位运算】只出现一次的数字
    【LeetCode-查找】山脉数组中查找目标值
    【LeetCode-查找】寻找旋转排序数组中的最小值 II
    【LeetCode-查找】寻找旋转排序数组中的最小值
    Linux基础命令mount /umount
    磁盘分区(Gdisk分区)
    磁盘分区( Fdisk分区)
    Linux基础练习题7.31
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/12001219.html
Copyright © 2011-2022 走看看