ELK技术栈 - Elasticsearch 学习笔记(三)(下)

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: ELK技术栈 - Elasticsearch 学习笔记(三)(下)

空白搜索



搜索API最常用的一种形式就是空白搜索,也就是不加任何查询条件的,只是返回集群中所有 文档的搜索。


GET /_search


返回内容如下(有删减):


{
    "hits" : {
    "total" : 14,
    "hits" : [
        {
            "_index": "us",
            "_type": "tweet",
            "_id": "7",
            "_score": 1,
            "_source": {
                "date": "2014-09-17",
                "name": "John Smith",
                "tweet": "The Query DSL is really powerful and flexible",
                "user_id": 2
          }
        },
        ... 9 个结果被隐藏 ...
        ],
        "max_score" : 1
        },
            "took" : 4,
            "_shards" : {
                "failed" : 0,
                "successful" : 10,
                "total" : 10
        },
        "timed_out" : false
}


hits


返回内容中最重要的内容就是 hits  ,它指明了匹配查询的文档的 总数  , hits  数组里则会包 含前十个匹配文档——也就是搜索结果。

hits  数组中的每一条结果都包含了文档的 _index  ,  _type  以及 _id  信息,以及 _source  字 段。这也就意味着你可以直接从搜索结果中获取到整个文档的内容。这与其他搜索引擎只返 回给你文档编号,还需要自己去获取文档是截然不同的。

每一个元素还拥有一个 _score  字段。这个是相关性评分,这个数值表示当前文档与查询的匹 配程度。通常来说,搜索结果会先返回最匹配的文档,也就是说它们会按照 _score  由高至低进行排列。在这个例子中,我们并没有声明任何查询,因此 _score  就都会返回 1

max_score  数值会显示所有匹配文档中的 _score  的最大值。


took


took  数值告诉我们执行这次搜索请求所耗费的时间有多少毫秒。


shards


_shards  告诉了我们参与查询分片的总数,以及有多少 successful  和 failed  。通常情况下 我们是不会得到失败的反馈,但是有的时候它会发生。如果我们的服务器突然出现了重大事 故,然后我们丢失了同一个分片中主从两个版本的数据。在查询请求中,无法提供可用的备 份。这种情况下,Elasticsearch就会返回`failed提示,但是它还会继续返回剩下的内容。


timeout


timed_out  数值告诉了我们查询是否超时。通常,搜索请求不会超时。如果相比完整的结果 你更需要的是快速的响应时间,这是你可以指定 timeout  值,例如 10  、 "10ms"  (10毫秒) 或者 "1s"  (1秒钟):


GET /_search?timeout=10ms


Elasticsearch会尽可能地返回你指定时间内它所查到的内容


Timeout并不是终止者

这里应该强调一下 timeout  并不会终止查询,它只是会在你指定的时间内返回当时已经查询 到的数据,然后关闭连接。在后台,其他的查询可能会依旧继续,尽管查询结果已经被返回 了。 使用超时是因为你要保障你的品质,并不是因为你需要终止你的查询。


多索引,多类型


当我们没有特别指定一个索引或者类型的时候,我们将会搜索整个集群中的所有文档。 Elasticsearch会把搜索请求转发给集群中的每一个主从分片,然后按照结果的相关性得到前 十名,并将它们返回给我们。


URL 说明
/_search 搜索所有的索引和类型
/gb/_search 搜索索引 gb 中的所有类型
/gb,us/_search 搜索索引 gb 以及 us 中的所有类型
/g*,u*/_search 搜索所有以 g 或 u 开头的索引中的所有类型
/gb/user/_search 搜索索引 gb 中类型 user 内的所有文档
/gb,us/user,tweet/_search 搜索索引 gb 和 索引 us 中类型 user 以及类型 tweet 内的所有文档
/_all/user,tweet/_search 搜索所有索引中类型为 user 以及 tweet 内的所有文档


搜索一个拥有五个主分片的索引与搜索五个都只拥有一个主分片是完全一样的。


分页


与SQL使用 LIMIT  来控制单“页”数量类似,Elasticsearch使用的是 from  以及 size  两个参 数:


参数 说明
size 每次返回多少个结果,默认值为 10
from 忽略最初的几条结果,默认值为 0


假设每页显示5条结果,那么1至3页的请求就是:


GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10


当心不要一次请求过多或者页码过大的结果。它们会在返回前排序。一个请求会经过多个分 片。每个分片都会生成自己的排序结果。然后再进行集中整理,以确保最终结果的正确性。


分布式系统中的大页码页面为了说明白为什么页码过大的请求会产生问题,我们就先预想一下我们在搜索一个拥有5个主 分片的索引。当我们请求第一页搜索的时候,每个分片产生自己前十名,然后将它们返回给 请求节点,然后这个节点会将50条结果重新排序以产生最终的前十名。 现在想想一下我们想获得第1,000页,也就是第10,001到第10,010条结果,与之前同理,每一 个分片都会先产生自己的前10,010名,然后请求节点统一处理这50,050条结果,然后再丢弃 掉其中的50,040条!

现在你应该明白了,在分布式系统中,大页码请求所消耗的系统资源是呈指数式增长的。这 也是为什么网络搜索引擎不会提供超过1,000条搜索结果的原因。


精简 搜索



搜索的API分为两种:其一是通过参数来传递查询的“精简版”查询语句(query string),还有 一种是通过JSON来传达丰富的查询的完整版请求体(request body),这种搜索语言被称为 查询DSL。

查询语句在行命令中运行点对点查询的时候非常实用。比如我想要查询所有 tweet  类型中, 所有 tweet  字段为 "elasticsearch"  的文档:


GET /_all/tweet/_search?q=tweet:elasticsearch


下一个查询是想要寻找 name  字段为 "john"  且 tweet  字段为 "mary"  的文档,实际的查询就 是:


+name:john +tweet:mary


但是经过百分号编码(percent encoding)处理后,会让它看起来稍显神秘:


GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary


前缀 "+"  表示必须要满足我们的查询匹配条件,而前缀 "-"  则表示绝对不能匹配条件。没 有 +  或者 -  的表示可选条件。匹配的越多,文档的相关性就越大。


字段 _all


下面这条简单的搜索将会返回所有包含 "mary"  字符的文档:


GET /_search?q=mary


在之前的例子中,我们搜索 tweet  或者 name  中的文字。然而,搜索的结果显示 "mary"  在三 个不同的字段中:


  • 用户的名字为"Mary"
  • 6个"Mary"发送的推文
  • 1个"@mary“

那么Elasticsearch是如何找到三个不同字段中的内容呢?

当我们在索引一个文档的时候,Elasticsearch会将所有字段的数值都汇总到一个大的字符串,并将它索引成一个特殊的字段 _all  :


{
    "tweet": "However did I manage before Elasticsearch?",
    "date": "2014-09-14",
    "name": "Mary Jones",
    "user_id": 1
}


就好像我们已经添加了一个叫做 _all  的字段:


"However did I manage before Elasticsearch? 2014-09-14 Mary Jones 1"


除非指定了字段名,不然查询语句就会搜索字段 _all  。


TIP: 在你刚开始创建程序的时候你可能会经常使用 _all  这个字段。但是慢慢的,你可能就会 在请求中指定字段。当字段 _all  已经没有使用价值的时候,那就可以将它关掉。之后的《字 段all》一节中将会有介绍


更加复杂的查询


再实现一个查询:

  • 字段 name  包含 "mary"  或 "john"
  • date  大于 2014-09-10
  • _all  字段中包含 "aggregations"  或 "geo"


+name:(mary john) +date:>2014-09-10 +(aggregations geo)


最终处理完的语句可读性可能很差:


?q=%2Bname%3A(mary+john)+%2Bdate%3A%3E2014-09-10+%2B(aggregations+geo)


最后要提一句,任何用户都可以通过查询语句来访问臃肿的查询,或许会得到一些私人的信息,或许会通过大量的运算将你的集群压垮!


TIP 出于以上原因,我们不建议你将查询语句直接暴露给用户,除非是你信任的可以访问数据与 集群的权限用户。


映射与统计



当我们在进行搜索的事情,我们会发现有一些奇怪的事情。比如有一些内容似乎是被打破 了:在我们的索引中有12条推文,中有一个包含了 2014-09-15  这个日期,但是看看下面的查 询结果中的总数量:


GET /_search?q=2014 # 12 results
GET /_search?q=2014-09-15 # 12 results !
GET /_search?q=date:2014-09-15 # 1 result
GET /_search?q=date:2014 # 0 results !


为什么我们使用字段 _all  搜索全年就会返回所有推文,而使用字段 date  搜索年份却没有结 果呢?为什么使用两者所得到的结果是不同的?

推测大概是因为我们的数据在 _all  和 date  在索引时没有被相同处理。我们来看看 Elasticsearch是如何处理我们的文档结构的。我们可以对 gb  的 tweet  使用mapping请求:


GET /gb/_mapping/tweet


{
    "gb": {
        "mappings": {
            "tweet": {
                "properties": {
                    "date": {
                      "type": "date",
                      "format": "dateOptionalTime"
                    },
                    "name": {
                      "type": "string"
                    },
                    "tweet": {
                      "type": "string"
                    },
                    "user_id": {
                      "type": "long"
                    }
                }
            }
        }
    }
}


Elasticsearch会根据系统自动判断字段类型并生成一个映射。返回结果告诉我们 date  字段被 识别成了 date  类型。 _all  没有出现是因为他是默认字段,但是我们知道字段 _all  实际上 是 string  类型的。


所以类型为 date  的字段和类型为 string  的字段的索引方式是不同的。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
5天前
|
SQL JSON API
ELK技术栈 - Elasticsearch 学习笔记(三)
ELK技术栈 - Elasticsearch 学习笔记(三)
43 0
|
5天前
|
JSON 数据可视化 应用服务中间件
ELK技术栈 - Kibana 学习笔记
ELK技术栈 - Kibana 学习笔记
42 0
|
5天前
|
存储 JSON API
ELK技术栈 - Elasticsearch 学习笔记(二)
ELK技术栈 - Elasticsearch 学习笔记(二)
208 0
|
5天前
|
Java Maven 开发工具
【ElasticSearch 】IK 分词器安装
【ElasticSearch 】IK 分词器安装
24 1
|
5天前
|
数据可视化 索引
elasticsearch head、kibana 安装和使用
elasticsearch head、kibana 安装和使用
|
5天前
|
存储 负载均衡 索引
linux7安装elasticsearch-7.4.0集群配置
linux7安装elasticsearch-7.4.0集群配置
115 0
|
5天前
|
Java Windows
windows下 安装 Elasticsearch报错warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME
windows下 安装 Elasticsearch报错warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME
47 0
|
5天前
|
搜索推荐 Java 大数据
ElasticSearch安装
ElasticSearch安装
|
5天前
|
JSON Unix Linux
Elasticsearch如何安装
Elasticsearch如何安装
|
5天前
|
存储 数据可视化 数据挖掘
【ElasticSearch】ElasticSearch安装
【ElasticSearch】ElasticSearch安装
28 2

热门文章

最新文章