zoukankan      html  css  js  c++  java
  • elasticsearch简单操作(二)

      让我们建立一个员工目录,假设我们刚好在Megacorp工作,这时人力资源部门出于某种目的需要让我们创建一个员工目录,这个目录用于促进人文关怀和用于实时协同工作,所以它有以下不同的需求:
    1、数据能够包含多个值的标签、数字和纯文本。
    2、检索任何员工的所有信息。
    3、支持结构化搜索,例如查找30岁以上的员工。
    4、支持简单的全文搜索和更复杂的短语(phrase)搜索
    5、高亮搜索结果中的关键字
    6、能够利用图表管理分析这些数据

    索引员工文档

    我们首先要做的是存储员工数据,每个文档代表一个员工。在Elasticsearch中存储数据的行为就叫做索引(indexing),不过在索引之前,我们需要明确数据应该存储在哪里。在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中,我们可以画一些简单的对比图来类比传统关系型数据库:

    Relational DB -> Databases -> Tables -> Rows -> Columns
    Elasticsearch -> Indices -> Types -> Documents -> Fields

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

    「索引」含义的区分

    你可能已经注意到索引(index)这个词在Elasticsearch中有着不同的含义,所以有必要在此做一下区分:

    1、索引(名词) 如上文所述,一个索引(index)就像是传统关系数据库中的数据库,它是相关文档存储的地方,index的复数是indices 或indexes。

    2、索引(动词) 「索引一个文档」表示把一个文档存储到索引(名词)里,以便它可以被检索或者查询。这很像SQL中的 INSERT 关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。

    3、倒排索引 传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。Elasticsearch和Lucene使用一种叫做倒排索引(inverted index)的数据结构来达到相同目的。

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

    所以为了创建员工目录,我们将进行如下操作:

    1、为每个员工的文档(document)建立索引,每个文档包含了相应员工的所有信息。
    2、每个文档的类型为 employee 。
    3、employee 类型归属于索引 megacorp 。
    4、megacorp 索引存储在Elasticsearch集群中。

    实际上这些都是很容易的(尽管看起来有许多步骤)。我们能通过一个命令执行完成的操作:

    插入员工1的信息

    curl -H "Content-Type: application/json" -X PUT 'http://localhost:9200/megacorp/employee/1' -d ''' -
    {                     
    "first_name" : "john",
    "last_name" : "Smith",
    "age" : 25,                            
    "about" : "I love to go rock climbing",
    "interests" : ["sports","music"]
    }'

    插入员工2的信息

    curl -H "Content-Type: application/json" -X PUT 'http://localhost:9200/megacorp/employee/2' -d '
    {
    "first_name" : "jane",
    "last_name" : "Smith",
    "age" : 32,
    "about" : "I like to collect rock albums",
    "interests" : ["music"]
    }'
    

     插入员工3的信息

    curl -H "Content-Type: application/json" -X PUT 'http://localhost:9200/megacorp/employee/3' -d '
    {
    "first_name" : "Douglas",
    "last_name" : "Fir",
    "age" : 35,
    "about" : "I like to build cabinets",
    "interests" : ["forestry"]
    }'

    检索文档

    获取员工1的信息

    curl -X GET 'http://localhost:9200/megacorp/employee/1?pretty'
    {
      "_index" : "megacorp",
      "_type" : "employee",
      "_id" : "1",
      "_version" : 1,
      "found" : true,
      "_source" : {
        "first_name" : "john",
        "last_name" : "Smith",
        "age" : 25,
        "about" : "I love to go rock climbing",
        "interests" : [
          "sports",
          "music"
        ]
      }
    }

    我们尝试一个最简单的搜索全部员工的请求

     

    curl -X GET 'http://localhost:9200/megacorp/employee/_search?pretty'
    {
      "took" : 9,
      "timed_out" : false,
      "_shards" : {
        "total" : 5,
        "successful" : 5,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : 3,
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "megacorp",
            "_type" : "employee",
            "_id" : "2",
            "_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" : "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" : "Douglas",
              "last_name" : "Fir",
              "age" : 35,
              "about" : "I like to build cabinets",
              "interests" : [
                "forestry"
              ]
            }
          }
        ]
      }
    }

    你可以看到我们依然使用 megacorp 索引和 employee 类型,但是我们在结尾使用关键字 _search 来取代原来的文档ID。响应内容的 hits 数组中包含了我们所有的三个文档。默认情况下搜索会返回前10个结果。

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

    curl -X GET 'http://localhost:9200/megacorp/employee/_search?q=last_name:Smith'
    {"took":20,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":2,"max_score":0.2876821,"hits":[{"_index":"megacorp","_type":"employee","_id":"2","_score":0.2876821,"_source":
    {
    "first_name" : "jane",
    "last_name" : "Smith",
    "age" : 32,
    "about" : "I like to collect rock albums",
    "interests" : ["music"]
    }},{"_index":"megacorp","_type":"employee","_id":"1","_score":0.2876821,"_source":
    {
    "first_name" : "john",
    "last_name" : "Smith",
    "age" : 25,
    "about" : "I love to go rock climbing",
    "interests" : ["sports","music"]
    }}]}}

    使用DSL语句查询

    查询字符串搜索便于通过命令行完成特定(ad hoc)的搜索,但是它也有局限性(参阅简单搜索章节)。Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。我们可以这样表示之前关于“Smith”的查询:

    [dyh@ump-pc1 root]$ curl -H "Content-Type: application/json" -X GET 'http://localhost:9200/megacorp/employee/_search' -d '
    {
    "query" : {
    "match" : {"last_name" : "Smith"}
    }}'
    {"took":53,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":2,"max_score":0.2876821,"hits":[{"_index":"megacorp","_type":"employee","_id":"2","_score":0.2876821,"_source":
    {
    "first_name" : "jane",
    "last_name" : "Smith",
    "age" : 32,
    "about" : "I like to collect rock albums",
    "interests" : ["music"]
    }},{"_index":"megacorp","_type":"employee","_id":"1","_score":0.2876821,"_source":
    {
    "first_name" : "john",
    "last_name" : "Smith",
    "age" : 25,
    "about" : "I love to go rock climbing",
    "interests" : ["sports","music"]
    }}]}}

    更复杂的搜索

    我们让搜索稍微再变的复杂一些。我们依旧想要找到姓氏为“Smith”的员工,但是我们只想得到年龄大于30岁的员工。我们的语句将添加过滤器(filter),它使得我们高效率的执行一个结构化搜索:

    curl -H "Content-Type: application/json" -X GET 'http://localhost:9200/megacorp/employee/_search' -d '
    {
        "query" : {
            "bool": {
                "must": {
                    "match" : {
                        "last_name" : "smith"  
                    }
                },
                "filter": {
                    "range" : {
                        "age" : { "gt" : 30 }  
                    }
                }
            }
        }
    }'

    结果显示:

    {"took":9,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":1,"max_score":0.2876821,"hits":[{"_index":"megacorp","_type":"employee","_id":"2","_score":0.2876821,"_source":
    {
    "first_name" : "jane",
    "last_name" : "Smith",
    "age" : 32,
    "about" : "I like to collect rock albums",
    "interests" : ["music"]
    }}]}}

    这部分与我们之前使用的 match 查询 一样。 
    这部分是一个 range 过滤器 , 它能找到年龄大于 30 的文档,其中 gt 表示_大于(_great than)。 
    目前无需太多担心语法问题,后续会更详细地介绍。只需明确我们添加了一个 过滤器 用于执行一个范围查询,并复用之前的 match 查询。现在结果只返回了一个雇员,叫 Jane Smith,32 岁。

    bool简单介绍

    首先,简单介绍下bool,它是一种复合查询方式, 
    (参考:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/query-dsl-bool-query.html) 
    与匹配其他查询的布尔组合的文档相匹配的查询。bool查询映射到Lucene BooleanQuery。它是使用一个或多个布尔子句构建的,每个子句都有一个类型化的事件。发生的类型是:

    发生 描述 
    must 该条款(查询)必须出现在匹配的文件,并将有助于得分。 
    filter 子句(查询)必须出现在匹配的文档中。然而不像 must查询的分数将被忽略。Filter子句在过滤器上下文中执行,这意味着评分被忽略,子句被考虑用于高速缓存。

    should 子句(查询)应该出现在匹配的文档中。如果 bool查询位于查询上下文中并且具有mustorfilter子句,那么bool即使没有 should查询匹配,文档也将匹配查询。在这种情况下,这些条款仅用于影响分数。如果bool查询是过滤器上下文 或者两者都不存在,must或者filter至少有一个should查询必须与文档相匹配才能与bool查询匹配。这种行为可以通过设置minimum_should_match参数来显式控制 。

    must_not 子句(查询)不能出现在匹配的文档中。子句在过滤器上下文中执行,意味着评分被忽略,子句被考虑用于高速缓存。因为计分被忽略,0所有文件的分数被返回。

    即,must:必须匹配,filter:匹配的结果过滤,should:至少有一个 must_not:不能匹配

  • 相关阅读:
    使用 GPUOperator 与 KubeSphere 简化深度学习训练与 GPU 监控
    基于 WeDataSphere Prophecis 与 KubeSphere 构建云原生机器学习平台
    在 Kubernetes Pod 中如何获取客户端的真实 IP
    云原生的 WebAssembly 能取代 Docker 吗?
    KubeSphere 开源 KubeEye:Kubernetes 集群自动巡检工具
    对于 Serverless, DevOps, 多云及边缘可观察性的思考与实践
    终于可以像使用 Docker 一样丝滑地使用 Containerd 了
    你真的理解 Kubernetes 中的 requests 和 limits 吗?
    顶点(vertexs) 图元(primitives) 片元(fragments片断) 像素(pixels)
    GLUT回调函数
  • 原文地址:https://www.cnblogs.com/dyh004/p/9258071.html
Copyright © 2011-2022 走看看