Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

基本的ES概念用法 #32

Open
chaijinsong opened this issue Sep 24, 2019 · 0 comments
Open

基本的ES概念用法 #32

chaijinsong opened this issue Sep 24, 2019 · 0 comments
Labels
前端 前端相关文章

Comments

@chaijinsong
Copy link
Owner

  1. ES 是什么?

    是一个开源的搜索引擎,建立在一个全文搜索引擎库(Apache Lucene)基础上。ES使用java对Lucene进行了封装,隐藏了Lucene的复杂性,取而代之是提供一套简单的 RESTful API。

  2. 面向文档
    在应用程序中对象一般比较复杂,如果把这些对象存储在数据库中,使用关系型数据库的行和列来存储,那么必须将这个复杂对象扁平化,非常的麻烦。而ES是面向文档的,它存储整个对象或者文档,并且对每个文档的内容进行索引,使其能够被搜索到。这是ES支持复杂全文搜索的原因。我们搜索出来的一条数据就叫 文档

  3. 索引在ES中的不同含义
    索引(名词):

    ​ 一个 索引 类似于传统数据库中的一个 数据库 ,是存储关系型文档的地方

    索引(动词):

    索引 一个文档就睡存储一个文档到一个 索引(名词) 中,以便被检索和查询。

  4. 新增索引(名词)

    下面给ES中新增雇员数据

    PUT /megacorp/employee/1
    {
        "first_name" : "John",
        "last_name" :  "Smith",
        "age" :        25,
        "about" :      "I love to go rock climbing",
        "interests": [ "sports", "music" ]
    }

    路径 /megacorp/employee/1 包含了三部分信息:

    megacorp : 索引名词

    employee : 类型名称

    1 : 特定雇员的ID

  5. 搜索指定ID的雇员
    直接执行GET请求,指明文档的地址------ 索引库(索引名称)、类型和ID

    GET /megacorp/employee/1

    返回值为:

    {
      "_index" :   "megacorp", // 索引库(索引名称)
      "_type" :    "employee", // 类型
      "_id" :      "1", // Id
      "_version" : 1,
      "found" :    true,
      "_source" :  { // 存储的信息
          "first_name" :  "John",
          "last_name" :   "Smith",
          "age" :         25,
          "about" :       "I love to go rock climbing",
          "interests":  [ "sports", "music" ]
      }
    }
  6. 搜索所有人

    GET /megacorp/employee/_search

    返回结果包含了所有的人的文档,放在数组 hits 中。一个搜索默认返回十条结果

    {
      "took":      6,
      "timed_out": false,
      "_shards": { ... },
      "hits": {
        "total":     1,
        "max_score": 1,
        "hits": [
          {
            "_index" :   "megacorp", // 索引库(索引名称)
            "_type" :    "employee", // 类型
            "_id" :      "1", // Id
            "_version" : 1,
            "found" :    true,
            "_source" :  { // 存储的信息
                "first_name" :  "John",
                "last_name" :   "Smith",
                "age" :         25,
                "about" :       "I love to go rock climbing",
                "interests":  [ "sports", "music" ]
            }
          }
        ]
      }  
    }

    同理,搜索指定条件的文档(文档就是每个人的信息)
    GET /megacorp/employee/_search?q=last_name:Smith

    找出 last_nameSmith 的文档信息


    上面的搜索,都是很简单的搜索,直接写在请求的url中,但在这种搜索不够灵活强大,所以ES提供了 DSL 支持更复杂的查询语句,上面的搜索Smith 的查询,使用DSL来写:

    GET /megacorp/employee/_search
    {
        "query" : {
            "match" : {
                "last_name" : "Smith"
            }
        }
    }

    这里没有在url上写请求参数了,而是使用一个JSON格式的请求体替代,使用了 match 查询类型。

  7. 复杂的搜索

    需求:搜索名字为 Smith 的员工,并且只需要年龄大于 30 的。此时多个条件我们就需要使用过滤器 filter

    GET /megacorp/employee/_search
    {
        "query" : {
            "bool": {
                "must": {
                    "match" : {
                        "last_name" : "smith" 
                    }
                },
                "filter": { // 满足大于30岁的才不会被过滤掉
                    "range" : {
                        "age" : { "gt" : 30 } 
                    }
                }
            }
        }
    }

    过滤器用来执行一个范围查询

  8. 全文搜索
    上面的搜索都是比较简单的:单个姓名,通过年龄过滤。现在需要全文搜索,找出所有喜欢攀岩(rock climbing)的员工。
    这种情况传统的SQL就没那么容易完成了。看一下之前插入的员工信息:

    {
        "first_name" : "John",
        "last_name" :  "Smith",
        "age" :        25,
        "about" :      "I love to go rock climbing",
        "interests": [ "sports", "music" ]
    }

    他的 about 属性中是 I love to go rock climbing 并不是 rock climbing ,所以传统SQL去搜索就不那么好搜了,但是在ES中搜索是很简单的:

    GET /megacorp/employee/_search
    {
        "query" : {
            "match" : {
                "about" : "rock climbing"
            }
        }
    }

    得到的结果可能并不会一定包含 rock climbing 可能某个员工的 about 属性是 rock albums ,但是 ES 也会给我们返回出来,因为它觉得我们可能需要这个数据。但是他也会给数据进行排序,匹配程度高的在 hits 数组的前面。并且每个 文档 都会有一个 _score 属性,代表这个搜索出来的 文档 和搜索条件之间的一个 相关性 。就和google搜索一样,相关性更高的排在更上面

  9. 短语搜索
    上面的全文搜索是找属性中的独立单词,例如上面会搜索出带 rock 或者 climbing 的文档,但是如果想要的结果是 rock climbing 两个单词连接起来才算匹配上的话,就需要使用短语查询。上面使用的是 match 查询,现在想实现短语查询就要使用 match_phrase 查询

    GET /megacorp/employee/_search
    {
        "query" : {
            "match_phrase" : {
                "about" : "rock climbing"
            }
        }
    }
  10. 高亮搜索
    想在搜索结果中 高亮 部分文本片段,那么只需要多一个 highlight 参数就可以了。返回结果中会新增一个highlight 属性,该属性中返回的文本会加上 em 标签
    搜索喜欢 攀岩的员工

    GET /megacorp/employee/_search
    {
        "query" : {
            "match_phrase" : {
                "about" : "rock climbing"
            }
        },
        "highlight": {
            "fields" : {
                "about" : {}
            }
        }
    }

    结果:

    {
       ...
       "hits": {
          "total":      1,
          "max_score":  0.23013961,
          "hits": [
             {
                ...
                "_score":         0.23013961,
                "_source": {
                   "first_name":  "John",
                   "last_name":   "Smith",
                   "age":         25,
                   "about":       "I love to go rock climbing",
                   "interests": [ "sports", "music" ]
                },
                "highlight": { // 会将搜索的about属性中传入的字符串加上 em 高亮
                   "about": [
                      "I love to go <em>rock</em> <em>climbing</em>" 
                   ]
                }
             }
          ]
       }
    }
  11. 聚合(aggregations)
    基于数据生成一些分析结果。聚合 于 SQL 中的 GROUP By 类似,但是更加强大
    举个例子:挖掘出员工中最受欢迎的兴趣爱好

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

    返回值:aggregations.buckets 喜欢 music 的人最多,文档数(搜到喜欢music的人)为2

    {
       ...
       "hits": { ... },
       "aggregations": {
          "all_interests": {
             "buckets": [
                {
                   "key":       "music", 
                   "doc_count": 2
                },
                {
                   "key":       "forestry",
                   "doc_count": 1
                },
                {
                   "key":       "sports",
                   "doc_count": 1
                }
             ]
          }
       }
    }

    这个最受欢迎的数据并不需要我们手动去算,而是ES在搜索过程中动态生成的

    如果想进一步搜索指定姓名的人中最受欢迎的兴趣爱好可以构造一个组合查询

    GET /megacorp/employee/_search
    {
      "query": {
        "match": {
          "last_name": "smith"
        }
      },
      "aggs": {
        "all_interests": {
          "terms": {
            "field": "interests"
          }
        }
      }
    }

    上面的就是一些基础的语法,和概念。这些了解后,再后面的更复杂的搜索就更简单了。

@chaijinsong chaijinsong added the 前端 前端相关文章 label Sep 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
前端 前端相关文章
Projects
None yet
Development

No branches or pull requests

1 participant