ElasticSearch

简单操作可以直接使用ElasticsearchRespositor接口,复杂的使用ElasticsearchTemplate

查询

 1.单字符串全文查询

SearchQuery searchQuery=newNativeSearchQueryBuilder().withQuery(queryStringQuery(word)).withPageable(pageable).build();

2.某字段按字符串模糊查询

查询某个字段中模糊包含目标字符串,使用matchQuery

SearchQuery searchQuery=newNativeSearchQueryBuilder().withQuery(matchQuery("content",content)).withPageable(pageable).build();

3.PhraseMatch查询,短语匹配

和match查询类似,match_phrase查询首先解析查询字符串来产生一个词条列表。然后会搜索所有的词条,但只保留包含了所有搜索词条的文档,并且词条的位置要邻接。一个针对短语“中华共和国”的查询不会匹配“中华人民共和国”,因为没有含有邻接在一起的“中华”和“共和国”词条。

这种完全匹配比较严格,类似于数据库里的“%落日熔金%”这种,使用场景比较狭窄。如果我们希望能不那么严格,譬如搜索“中华共和国”,希望带“我爱中华人民共和国”的也能出来,就是分词后,中间能间隔几个位置的也能查出来,可以使用slop参数。

SearchQuery searchQuery=newNativeSearchQueryBuilder().withQuery(matchPhraseQuery("content",content)).withPageable(pageable).build();

4.multi_match多个字段匹配某字符串

如果我们希望title,content两个字段去匹配某个字符串,只要任何一个字段包括该字符串即可,就可以使用multimatch

SearchQuery searchQuery=newNativeSearchQueryBuilder().withQuery(multiMatchQuery(title,"title","content")).withPageable(pageable).build();

5.完全包含查询

之前的查询中,当我们输入“我天”时,ES会把分词后所有包含“我”和“天”的都查询出来,如果我们希望必须是包含了两个字的才能被查询出来,那么我们就需要设置一下Operator。

SearchQuery searchQuery=newNativeSearchQueryBuilder().withQuery(matchQuery("title",title).operator(MatchQueryBuilder.Operator.AND)).build();

6合并查询

即boolQuery,可以设置多个条件的查询方式。它的作用是用来组合多个Query,有四种方式来组合,must,mustnot,filter,should。

must代表返回的文档必须满足must子句的条件,会参与计算分值;

filter代表返回的文档必须满足filter子句的条件,但不会参与计算分值;

should代表返回的文档可能满足should子句的条件,也可能不满足,有多个should时满足任何一个就可以,通过minimum_should_match设置至少满足几个。

mustnot代表必须不满足子句的条件。

譬如我想查询title包含“XXX”,且userId=“1”,且weight最好小于5的结果。那么就可以使用boolQuery来组合。

SearchQuery searchQuery=newNativeSearchQueryBuilder().withQuery(boolQuery().must(termQuery("userId",userId)).should(rangeQuery("weight").lt(weight)).must(matchQuery("title",title))).build();

7过滤查询bool的使用

Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型

must

返回的文档必须满足must子句的条件,并且参与计算分值

filter

返回的文档必须满足filter子句的条件,但是不会像must一样,参与计算分值

should

返回的文档可能满足should子句的条件.在一个bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回.minimum_should_match参数定义了至少满足几个子句.

must_not

返回的文档必须不满足定义的条件

如果一个查询既有filter又有should,那么至少包含一个should子句.

bool查询也支持禁用协同计分选项disable_coord.一般计算分值的因素取决于所有的查询条件.

bool查询也是采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值.

8高亮查询

//高亮查询

HighlightBuilder highlightBuilder =new HighlightBuilder();

highlightBuilder.field(new HighlightBuilder.Field("message"));

highlightBuilder.preTags("<span style=\"color:red\">");  //高亮设置

highlightBuilder.postTags("</span>");

1.概念介绍

1.索引(index

相当于Mysql中的数据库(database),用于存放文档

2. 类型(type

相当于Mysql中的表(table),定义了相同数据结构的文档存放

3. 文档(document

相当于Mysql中的一行记录(row),是索引的基本单元,包含一个或多个键值对,表现形式就是json对象

4. 字段(filed)

相当于Mysql中的一列(column),是key-value形式的


一个运行中的ES实例是一个节点,一个集群中有一个或者多个节点,这些节点中的cluste.name是相同的。

我们在创建索引时可以指定这个索引的主分片数和副本分片数,默认是5个主分片,1个副本分片(5*1=5个分片)。这些分片会均匀的分布在集群的所有数据节点中。

在客户端发送请求时,集群中所有的节点都能处理这个请求,节点会找到文档所存储的分片,并在该分片所在的节点做检索,将结果返回给请求的那个节点做最终的过滤和组合,然后返回给客户端。

那么在往这个索引上面存储文档时,会存储到5个分片中的一个分片上,而这个路由是由下面的公式决定的

shard = hash(routing) % number_of_primary_shards

routing是可以设置的一个值,默认是文档的id

number_of_primary_shards是主分片的数量(5)

也正是这个公式的原因,所以规定了索引创建后不能修改主分片数

集群, 由多个节点组成,一个集群中有很多的很多个索引库

setting, 配置集群中索引库的信息, 每个索引库默认是5个分片2个副本

节点 , 一台物理机器

分片, 节点中存放的是某个索引库的一个分片.

文档, 文档就是数据库中的一行数据或者是一个爬虫爬取回来的网页信息或者是一个订单信息.

字段, 字段是文档中的属性(id, title, contend, author,time)

mapping, 描述字段的信息(是否分析,是否存储,是否索引等)

副本, 就是分片的备份, 保存数据不丢失.

文档

字段

mapping

2.使用方法


1.客户端连接

spring-boot-data-elasticsearch(ElasticsearchRespositor搭配ElasticsearchTemplate使用)

TransportClient(7以后不支持)

RestHighLevelClient(推荐使用,版本推荐7)

2.maven仓库

<properties>

    <!--不加请求会出现addParameters的报错,-->

    <elasticsearch.version>7.3.2</elasticsearch.version>

</properties>

<dependency>

    <groupId>org.elasticsearch</groupId>

    <artifactId>elasticsearch</artifactId>

   <version>7.3.2</version>

</dependency>

<dependency>

<groupId>org.elasticsearch.client</groupId>

    <artifactId>elasticsearch-rest-high-level-client</artifactId>

   <version>7.3.2</version>

</dependency>

3.初始化客户端

//初始化客户端

RestHighLevelClient client =new RestHighLevelClient(

RestClient.builder(

new HttpHost("集群",9200,"http")

)

);

//创建查询request

SearchRequest search =new SearchRequest();

//构建查询条件

SearchSourceBuilder sourceBuilder =new SearchSourceBuilder();

//matchQuery模糊查询

sourceBuilder.query(QueryBuilders.matchQuery("xx","yy"));

//queryStringQuery全文查询

sourceBuilder.query(QueryBuilders.queryStringQuery("xx"));

//短语匹配 ,和match查询类似,match_phrase查询首先解析查询字符串来产生一个词条列表。

// 然后会搜索所有的词条,但只保留包含了所有搜索词条的文档,并且词条的位置要邻接。

// 一个针对短语“中华共和国”的查询不会匹配“中华人民共和国”,因为没有含有邻接在一起的“中华”和“共和国”词条。

sourceBuilder.query(QueryBuilders.matchPhraseQuery("xx","yy"));

//multi_match多个字段匹配某字符串

sourceBuilder.query(QueryBuilders.multiMatchQuery("xx","yy","zz"));

//完全包含查询,之前的查询中,当我们输入“我天”时,ES会把分词后所有包含“我”和“天”的都查询出来

//如果我们希望必须是包含了两个字的才能被查询出来,那么我们就需要设置一下Operator。and或者or

sourceBuilder.query(QueryBuilders.matchQuery("xx","yy").operator(Operator.AND));

//BoolQueryBuilder合并查询,使用合并查询可以把多个查询条件合并到一起

BoolQueryBuilder boolQuery =new BoolQueryBuilder();

//范围查询

boolQuery.must(QueryBuilders.rangeQuery("xx")

.gt("zz")

.lt("mm"));

sourceBuilder.query(boolQuery);

//把查询条件添加到查询request中

search.source(sourceBuilder);

//同步调用

SearchResponse response = client.search(search, RequestOptions.DEFAULT);

//异步调用

client.searchAsync(search, RequestOptions.DEFAULT, new ActionListener() {

@Override

    public void onResponse(SearchResponse searchResponse) {

}

@Override

    public void onFailure(Exception e) {

}

});

3.集群

1.ES 选主流程

每个节点结算最小的ID,把它选举为临时Master,然后对该master进行投票;

每个节点收集票数,当票数大于指定的法定个数时,成为Master,然后对加入的节点进行集群信息广播。

法定个数:有Master资格的节点数: (n/2 + 1 )

流程描述

服务启动后,进行ping操作,ping所有的节点,然后得到一个fullPingResponses,本节点也加入该list;

创建两个列表

活动的Master列表 activeMasters:遍历刚刚的fullPingResponses然后将每个节点认为的Master存入该list,正常情况下是只有一个Master;

候选Master列表 candidateMasters:遍历刚刚的fullPingResponses然后将具备Master节点资格的节点加入此list;

如果activeMasters不为空,则从activeMasters中选择,否则从candidateMasters中选择,从候选列表选择时要先判断候选者列表大小是否大于法定人数,否则失败;

在从列表进行选择时,直接对列表进行排序,然后选出最小ID的节点充当临时节点;

开始进行投票,每个节点都向自己认为的Master进行joinRequest请求,此时会有两种情况

本节点是Master时:此时该节点进行统计,统计发送过来的joinRequest个数,如果在指定的时间(默认30s,可配置)内达到法定人数,发布集群信息,并回复joinRequest请求,最后完成选举,否则选举失败;

本节点不是Master时:拒绝其他节点joinRequest,向其认为的Master发送joinRequest请求,并等待,如果在指定的时间(1min,可配置)未收到回复或异常重试3次都失败了则选举失败,重新尝试;如果收到的回复中没有Master信息或者Master信息不是之前选择的临时Master节点则选举失败。

2.垃圾回收

不要更改默认的垃圾回收器!

Elasticsearch 默认的垃圾回收器( GC )是 CMS。 这个垃圾回收器可以和应用并行处理,以便它可以最小化停顿。 然而,它有两个 stop-the-world 阶段,处理大内存也有点吃力。

尽管有这些缺点,它还是目前对于像 Elasticsearch 这样低延迟需求软件的最佳垃圾回收器。官方建议使用 CMS。

3.重要配置修改

#数据保存路径,你可以通过逗号分隔指定多个目录。

path.data: /path/to/data1,/path/to/data2 

日志路径

path.logs: /path/to/logs

# 插件路径

path.plugins: /path/to/plugins

#最小主节点数

discovery.zen.minimum_master_nodes: 2


3.日志

Elasticsearch 会输出很多日志,都放在 ES_HOME/logs 目录下。默认的日志记录等级是 INFO 。它提供了适度的信息,但是又设计好了不至于让你的日志太过庞大。

你 可以 修改 logging.yml 文件然后重启你的节点——但是这样做即繁琐还会导致不必要的宕机时间。作为替代,你可以通过 cluster-settings API 更新日志记录级别,就像我们前面刚学过的那样。

要实现这个更新,选择你感兴趣的日志器,然后在前面补上 logger. 。对根日志器你可以用 logger._root 来表示。

让我们调高节点发现的日志记录级别:

PUT /_cluster/settings

{  

  "transient" :

       {  

         "logger.discovery" : "DEBUG"   

         }

}

还有另一个日志叫 慢日志 。这个日志的目的是捕获那些超过指定时间阈值的查询和索引请求。这个日志用来追踪由用户产生的很慢的请求很有用。

默认情况,慢日志是不开启的。要开启它,需要定义具体动作(query,fetch 还是 index),你期望的事件记录等级( WARN 、 DEBUG 等),以及时间阈值。

这是一个索引级别的设置,也就是说可以独立应用给单个索引:

PUT /my_index/_settings{  

 "index.search.slowlog.threshold.query.warn" : "10s",     "index.search.slowlog.threshold.fetch.debug": "500ms",     "index.indexing.slowlog.threshold.index.info": "5s" 

}

查询慢于 10 秒输出一个 WARN 日志。

获取慢于 500 毫秒输出一个 DEBUG 日志。

索引慢于 5 秒输出一个 INFO 日志。

你也可以在 elasticsearch.yml 文件里定义这些阈值。没有阈值设置的索引会自动继承在静态配置文件里配置的参数。

一旦阈值设置过了,你可以和其他日志器一样切换日志记录等级:

PUT /_cluster/settings

{  

   "transient" :

       {      

  "logger.index.search.slowlog" : "DEBUG",

   "logger.index.indexing.slowlog" : "WARN"

      }

}

设置搜索慢日志为 DEBUG 级别。

设置索引慢日志为 WARN 级别。



面试-------------------------

Elasticsearch 查询数据的工作原理是什么?

ES 写入数据的工作原理是什么啊?ES 查询数据的工作原理是什么啊?底层的 Lucene 介绍一下呗?倒排索引了解吗?

面试官心理分析

问这个,其实面试官就是要看看你了解不了解 es 的一些基本原理,因为用 es 无非就是写入数据,搜索数据。你要是不明白你发起一个写入和搜索请求的时候,es 在干什么,那你真的是......

对 es 基本就是个黑盒,你还能干啥?你唯一能干的就是用 es 的 api 读写数据了。要是出点什么问题,你啥都不知道,那还能指望你什么呢?

面试题剖析

es 写数据过程

客户端选择一个 node 发送请求过去,这个 node 就是coordinating node(协调节点)。

coordinating node对 document 进行路由,将请求转发给对应的 node(有 primary shard)。

实际的 node 上的primary shard处理请求,然后将数据同步到replica node。

coordinating node如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端。

es-write

es 读数据过程

可以通过doc id来查询,会根据doc id进行 hash,判断出来当时把doc id分配到了哪个 shard 上面去,从那个 shard 去查询。

客户端发送请求到任意一个 node,成为coordinate node。

coordinate node对doc id进行哈希路由,将请求转发到对应的 node,此时会使用round-robin随机轮询算法,在primary shard以及其所有 replica 中随机选择一个,让读请求负载均衡。

接收请求的 node 返回 document 给coordinate node。

coordinate node返回 document 给客户端。

es 搜索数据过程

es 最强大的是做全文检索,就是比如你有三条数据:

java真好玩儿啊

java好难学啊

j2ee特别牛Copy to clipboardErrorCopied

你根据java关键词来搜索,将包含java的document给搜索出来。es 就会给你返回:java真好玩儿啊,java好难学啊。

客户端发送请求到一个coordinate node。

协调节点将搜索请求转发到所有的 shard 对应的primary shard或replica shard,都可以。

query phase:每个 shard 将自己的搜索结果(其实就是一些doc id)返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。

fetch phase:接着由协调节点根据doc id去各个节点上拉取实际的document数据,最终返回给客户端。

写请求是写入 primary shard,然后同步给所有的 replica shard;读请求可以从 primary shard 或 replica shard 读取,采用的是随机轮询算法。

写数据底层原理

es-write-detail

先写入内存 buffer,在 buffer 里的时候数据是搜索不到的;同时将数据写入 translog 日志文件。

如果 buffer 快满了,或者到一定时间,就会将内存 buffer 数据refresh到一个新的segment file中,但是此时数据不是直接进入segment file磁盘文件,而是先进入os cache。这个过程就是refresh。

每隔 1 秒钟,es 将 buffer 中的数据写入一个新的segment file,每秒钟会产生一个新的磁盘文件segment file,这个segment file中就存储最近 1 秒内 buffer 中写入的数据。

但是如果 buffer 里面此时没有数据,那当然不会执行 refresh 操作,如果 buffer 里面有数据,默认 1 秒钟执行一次 refresh 操作,刷入一个新的 segment file 中。

操作系统里面,磁盘文件其实都有一个东西,叫做os cache,即操作系统缓存,就是说数据写入磁盘文件之前,会先进入os cache,先进入操作系统级别的一个内存缓存中去。只要buffer中的数据被 refresh 操作刷入os cache中,这个数据就可以被搜索到了。

为什么叫 es 是准实时的?NRT,全称near real-time。默认是每隔 1 秒 refresh 一次的,所以 es 是准实时的,因为写入的数据 1 秒之后才能被看到。可以通过 es 的restful api或者java api,手动执行一次 refresh 操作,就是手动将 buffer 中的数据刷入os cache中,让数据立马就可以被搜索到。只要数据被输入os cache中,buffer 就会被清空了,因为不需要保留 buffer 了,数据在 translog 里面已经持久化到磁盘去一份了。

重复上面的步骤,新的数据不断进入 buffer 和 translog,不断将buffer数据写入一个又一个新的segment file中去,每次refresh完 buffer 清空,translog 保留。随着这个过程推进,translog 会变得越来越大。当 translog 达到一定长度的时候,就会触发commit操作。

commit 操作发生第一步,就是将 buffer 中现有数据refresh到os cache中去,清空 buffer。然后,将一个commit point写入磁盘文件,里面标识着这个commit point对应的所有segment file,同时强行将os cache中目前所有的数据都fsync到磁盘文件中去。最后清空现有 translog 日志文件,重启一个 translog,此时 commit 操作完成。

这个 commit 操作叫做flush。默认 30 分钟自动执行一次flush,但如果 translog 过大,也会触发flush。flush 操作就对应着 commit 的全过程,我们可以通过 es api,手动执行 flush 操作,手动将 os cache 中的数据 fsync 强刷到磁盘上去。

translog 日志文件的作用是什么?你执行 commit 操作之前,数据要么是停留在 buffer 中,要么是停留在 os cache 中,无论是 buffer 还是 os cache 都是内存,一旦这台机器死了,内存中的数据就全丢了。所以需要将数据对应的操作写入一个专门的日志文件translog中,一旦此时机器宕机,再次重启的时候,es 会自动读取 translog 日志文件中的数据,恢复到内存 buffer 和 os cache 中去。

translog 其实也是先写入 os cache 的,默认每隔 5 秒刷一次到磁盘中去,所以默认情况下,可能有 5 秒的数据会仅仅停留在 buffer 或者 translog 文件的 os cache 中,如果此时机器挂了,会丢失5 秒钟的数据。但是这样性能比较好,最多丢 5 秒的数据。也可以将 translog 设置成每次写操作必须是直接fsync到磁盘,但是性能会差很多。

实际上你在这里,如果面试官没有问你 es 丢数据的问题,你可以在这里给面试官炫一把,你说,其实 es 第一是准实时的,数据写入 1 秒后可以搜索到;可能会丢失数据的。有 5 秒的数据,停留在 buffer、translog os cache、segment file os cache 中,而不在磁盘上,此时如果宕机,会导致 5 秒的数据丢失

总结一下,数据先写入内存 buffer,然后每隔 1s,将数据 refresh 到 os cache,到了 os cache 数据就能被搜索到(所以我们才说 es 从写入到能被搜索到,中间有 1s 的延迟)。每隔 5s,将数据写入 translog 文件(这样如果机器宕机,内存数据全没,最多会有 5s 的数据丢失),translog 大到一定程度,或者默认每隔 30mins,会触发 commit 操作,将缓冲区的数据都 flush 到 segment file 磁盘文件中。

数据写入 segment file 之后,同时就建立好了倒排索引。

删除/更新数据底层原理

如果是删除操作,commit 的时候会生成一个.del文件,里面将某个 doc 标识为deleted状态,那么搜索的时候根据.del文件就知道这个 doc 是否被删除了。

如果是更新操作,就是将原来的 doc 标识为deleted状态,然后新写入一条数据。

buffer 每 refresh 一次,就会产生一个segment file,所以默认情况下是 1 秒钟一个segment file,这样下来segment file会越来越多,此时会定期执行 merge。每次 merge 的时候,会将多个segment file合并成一个,同时这里会将标识为deleted的 doc 给物理删除掉,然后将新的segment file写入磁盘,这里会写一个commit point,标识所有新的segment file,然后打开segment file供搜索使用,同时删除旧的segment file。

底层 lucene

简单来说,lucene 就是一个 jar 包,里面包含了封装好的各种建立倒排索引的算法代码。我们用 Java 开发的时候,引入 lucene jar,然后基于 lucene 的 api 去开发就可以了。

通过 lucene,我们可以将已有的数据建立索引,lucene 会在本地磁盘上面,给我们组织索引的数据结构。

倒排索引

在搜索引擎中,每个文档都有一个对应的文档 ID,文档内容被表示为一系列关键词的集合。例如,文档 1 经过分词,提取了 20 个关键词,每个关键词都会记录它在文档中出现的次数和出现位置。

那么,倒排索引就是关键词到文档ID 的映射,每个关键词都对应着一系列的文件,这些文件中都出现了关键词。

举个栗子。

有以下文档:

DocIdDoc

1谷歌地图之父跳槽 Facebook

2谷歌地图之父加盟 Facebook

3谷歌地图创始人拉斯离开谷歌加盟 Facebook

4谷歌地图之父跳槽 Facebook 与 Wave 项目取消有关

5谷歌地图之父拉斯加盟社交网站 Facebook

对文档进行分词之后,得到以下倒排索引

WordIdWordDocIds

1谷歌1, 2, 3, 4, 5

2地图1, 2, 3, 4, 5

3之父1, 2, 4, 5

4跳槽1, 4

5Facebook1, 2, 3, 4, 5

6加盟2, 3, 5

7创始人3

8拉斯3, 5

9离开3

10与4

......

另外,实用的倒排索引还可以记录更多的信息,比如文档频率信息,表示在文档集合中有多少个文档包含某个单词。

那么,有了倒排索引,搜索引擎可以很方便地响应用户的查询。比如用户输入查询Facebook,搜索系统查找倒排索引,从中读出包含这个单词的文档,这些文档就是提供给用户的搜索结果。

要注意倒排索引的两个重要细节:

倒排索引中的所有词项对应一个或多个文档;

倒排索引中的词项根据字典顺序升序排列

上面只是一个简单的例子,并没有严格按照字典顺序升序排列。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • ES 全文搜索 全文搜索 使用了match查询的多词查询只是简单地将生成的term查询包含在了一个bool查询中。...
    王某某的笔记阅读 3,474评论 0 2
  • 1.基于Term的查询 Term是表达语义的最小单位,搜索和自然语言处理都用Term处理。 Term级别的查询:T...
    鸿雁长飞光不度阅读 726评论 0 0
  • [TOC] 一、DSL 在 ElasticSearch 中,提供了功能十分丰富、多种表现形式的查询语言—— DSL...
    w1992wishes阅读 2,103评论 0 3
  • Filter DSL 过滤 term 过滤 term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_a...
    tkpy阅读 404评论 0 1
  • es种有两种查询模式,一种是像传递URL参数一样去传递查询语句,被称为简单搜索或查询字符串(query strin...
    会武功的蚊子阅读 539评论 1 3