文章目录
全文搜索引擎Elasticsearch
Elasticsearch简介
Elasticsearch是一个基于Lucene库的搜索引擎。它提供了一个分布式、支持多租户的全文搜索引擎,具有HTTP Web接口和无模式JSON文档。Elasticsearch是用Java开发的,并在Apache许可证下作为开源软件发布。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。[5]根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。[6]
Elasticsearch是与名为Logstash的数据收集和日志解析引擎以及名为Kibana的分析和可视化平台一起开发的。这三个产品被设计成一个集成解决方案,称为“Elastic Stack”(以前称为“ELK stack”)。
Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。[5]”Elasticsearch是分布式的,这意味着索引可以被分成分片,每个分片可以有0个或多个副本。每个节点托管一个或多个分片,并充当协调器将操作委托给正确的分片。再平衡和路由是自动完成的。“[5]相关数据通常存储在同一个索引中,该索引由一个或多个主分片和零个或多个复制分片组成。一旦创建了索引,就不能更改主分片的数量。[7]
Elasticsearch使用Lucene,并试图通过JSON和Java API提供其所有特性。它支持facetting和percolating[8],如果新文档与注册查询匹配,这对于通知非常有用。
另一个特性称为“网关”,处理索引的长期持久性;例如,在服务器崩溃的情况下,可以从网关恢复索引。[9]Elasticsearch支持实时GET请求,适合作为NoSQL数据存储[10],但缺少分布式事务。——来自于维基百科
Elasticsearch简称es,概要:
- 是一个开源的高扩展的分布式全文检索引擎
- 近乎实时的存储、检索数据
- 本身扩展性好,支持集群,可以处理PB级别的数据,1024TB = 1PB
- Elasticsearch 在 Lucene 的基础上进行封装,实现了分布式搜索引擎
- es也使用 Java 开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API—HTTP/https来隐藏Lucene的复杂性;而restful风格遵循的是 http/https 协议
- es是一个 java 项目
为什么使用Elasticsearch?
原因:
随着数据量越来越大,作为 Lucene 也感到吃力,将所有的数据分析后存放到一个索引库中,造成性能的降低。而 Elasticsearch 支持集群和分布式,很好的解决了这一问题,而解决这一问题的根本是 “分片”。
分片:当数据大时,不仅存储会降低效率,而且一旦数据丢失那么后果是很严重的。而 es 中提供了分片的概念,它将数据均衡的分配(使用“一致性Hash”)提高了性能。并且其分片还有一个复制的功能,这个功能是给主分片做一个备份,保证当主分片出问题时,备份会将其修复,备份也成为 副本。而副本并不做搜索的作用!
注意:分片的作用在单节点下并没什么用处,主要作用在集群环境中。在集群环境中,主分片和副本都会散布在各节点中,并且是均衡分配。还有一个注意事项就是 主分片和副本不可能在同一节点上!
Elasticsearch 与Solr的对比
- Solr 利用 zookeoper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
- Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
- Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
- Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch 当单纯的对已有数据进行搜索时,Solr更快,当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。综上所述,
- Solr的架构不适合实时搜索的应用。Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。
Elasticsearch 的安装和使用
注意
Elasticsearch是使用 Java 开发的,所以需要最好使用 jdk1.8 以上的版本。这里设计到的是 es 5.0+ 的版本,6以上版本的还没去了解就不说了,不过5跟6版本区别还是有点大的,5+版本更加稳定。有 jdk1.8+以上版本还不够,请确保是否已经配置的 jdk环境变量,否则 es 服务会启动失败。
安装
直接上官网安装就得了,官网地址: https://www.elastic.co/products/elasticsearch
步骤
-
这里使用的是window版本,将下载好的 ES 压缩包解压就完成了,没什么多大问题!
-
进入bin目录启动服务,
elasticsearch.bat -
有个config目录,这是存放配置文件的,
elasticsearch.yml这里面可以改 集群标识名、端口号等 -
图形化界面,直接用谷歌浏览器,去谷歌插件商店下载
elasticsearch head搞定! -
在浏览器访问
http://localhost:9200得到如下信息,就安装成功了。

注意:如果在配置文件中改了端口,那么访问的地址也要改成对应的端口。
Elasticsearch 概念
Elasticsearch 与数据库对比
个人觉得用比较会更直观更好的理解,拿mysql数据库为例:
| mysql | elasticsearch |
|---|---|
| Database(数据库) | Indices(索引库) |
| Table(数据表) | Type(类型) |
| Rows(表中的一行数据) | Documents(文档对象) |
| Columns(字段名) | Fields |
| Index(字段对应的值) | Index(一样,其实也就是数据) |
可以看出两个很相似,这样看上去如果不好理解,那么配合图形界面来理解会比较容易!

Elasticsearch 概念
这里概念就不细说了,官方文档更直观一点。
- 集群 cluster:Elasticsearch 的好处就是支持集群,一个集群是由一个或多个节点组织在一起的。共同拥有整个数据,一起提供索引和搜索功能(分片提供的)。一个集群会有一个唯一的名称标识,不配置默认集群名为
elasticsearch,如需要修改则取 Elasticsearch 的配置文件修改即可。只要节点的集群名称相同,就可以加入同一个集群中。 - 节点node:一个节点是集群中的一个服务器,作为集群的一部分。
- 索引 Indices:就是索引库,放索引(数据)的。
- 类型 type:在一个索引中,你可以定义一种或多种类型。其实也就是分门别类。比如冰箱、电视、洗衣机,都归为电器一类。这里面也是如此,没有强制要求。
- 文档 document:数据载体,一个文档是一个可被索引的基础信息单元。(json格式的数据)
- 分片和复制:一个索引可以存储超出单个节点硬件限制的大量数据。当索引(数据)过多过大时,可以通过分片将索引分成很多份,效率就能够提高。而复制也就是备份,起一个修复的作用。
- 映射 mapping:其实也就是做限制的,拿数据库举例,数据库中数据表的字段是不是有数据类型的限制,比如 varchar、int、date类型等,
elasticsearch中也就类型的限制,同样也是对字段进行限制。其不仅可以限制数据类型,而且还可以设置指定的分析器、默认值、是否被索引等等。。
Elasticsearch的Java Api
elasticsearch环境配置
流程:
- 创建maven工程,导依赖
- 因为遵循了restful风格,所以创建TransportClient通过传输模式来连接到一个
elasticsearch的集群,定义成静态工厂方法,方便调用 - 通过TransportClient对象创建索引库
步骤:
创建工程,导入依赖
<!-- es核心包 -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.8</version>
</dependency>
<!-- 传输包 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.8</version>
</dependency>
<!-- 日志包 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!-- 测试包,直接运行看效果 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<!-- jaskon包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.6</version>
</dependency>
创建传输客户端,之后直接调用即可
/**
* 1.创建settings对象,相当于是一个配置信息,配置集群的名称,不配置会默认使用elasticsearch
* 2.创建一个传输client对象
* 3.连接一个elasticsearch的集群
*/
public class IndexManager {
public static TransportClient getTransportClient() throws Exception {
// 1.创建settings对象,使用默认配置的集群
Settings settings = Settings.EMPTY;
//使用指定集群的配置
// Settings settings = Settings.builder().put("cluster.name","cluster-es").build();
// 2.创建一个传输client对象
TransportClient client = new PreBuiltTransportClient(settings);
// 3.连接一个elasticsearch的集群
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
// 返回一个client对象
return client;
}
}
创建索引库,方便测试都在同一个类中,后面直接写方法
//创建索引库
@Test
public void createIndexResp() throws Exception {
// 1.获取client对象
TransportClient client = getTransportClient();
// 2.Using an IndicesAdminClient, you can create an index with all default settings and no mapping: 通过索引管理对象,你可以创建一个默认无mapping配置的索引库(名称为blog),通过get发送请求给 es服务,es服务会返回一个响应数据(为json数据)。
CreateIndexResponse response = client.admin().indices().prepareCreate("blog").get();
//打印 response.isAcknowledged()为true则创建成功
System.out.println("response = " + response.isAcknowledged());
//关闭client对象,每次调用后都要关闭资源
client.close();
}
Elasticsearch 创建文档
创建文档对象
使用 java 的 api完成索引(数据)的创建,也就是对原始数据的写入索引库中。
- 使用XContentFactory.jsonBuilder创建
- 使用pojo实体类的方式创建
注意:不止这两种方式,最后都是用过json的格式传递
第一种方式:
@Test
public void createIndex() throws Exception {
// 1.获取client对象
TransportClient client = getTransportClient();
// 2.创建索引文档对象,文档数据为json格式,使用工厂类创建
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder()
.startObject() //开启json对象存储,相当于 {
.field("id", 1)
.field("title", "elasticsearch是一个基于lucene的搜索服务")
.field("content", "ElasticSearch是一个基于Lucene的搜索服务器。")
.endObject();//结束json对象存储,相当于 }
// 使用client对象将索引文档对象等,封装发送请求到es服务端,如果有索引库则插入数据,如果没有索引库则创建索引库
// setSource() :为存储其文档信息,
IndexResponse indexResponse = client
.prepareIndex("blog2", "content")
.setSource(xContentBuilder)
.get();
// 3.关闭资源
client.close();
}
第二种方式:需要先创建一个实体类(基本操作,这里不演示)
@Test
public void createIndex2() throws Exception {
// 1.获取client客户端对象
TransportClient client = getTransportClient();
// 2.创建实体类Blog对象,设置数据
Blog blog = new Blog();
blog.setId(3L); //long类型
blog.setTitle("elasticsearch是一个基于lucene的搜索服务"); //string类型
blog.setContent("elasticsearch是一个基于lucene的搜索服务"); //string类型
blog.setPrice(30.1f); //float类型
// 3.将对象转换json字符串
ObjectMapper objectMapper = new ObjectMapper();
String jsonData = objectMapper.writeValueAsString(blog);
// 4.封装数据,创建索引库
/*
* prepareIndex() :参数1:索引库名 参数2:type类型(表名) 参数3:索引库rows行id,不写会自动 * 生成16位码
* setSource():设置要封装发送的数据
*/
IndexResponse indexResponse = client
.prepareIndex("blog3", "article", blog.getId() + "")
.setSource(jsonData, XContentType.JSON)
.get();
// 5.关闭资源
client.close();
}
Elasticsearch 修改文档
修改文档也有两种方式
- 直接覆盖的方式:仍使用创建文档的步骤,根据表中每一行的
索引id进行修改,类似于数据库修改操作,通过条件修改 - 通过调用修改的方法进行修改,也是通过条件的判断来修改
第一种方式:
@Test
public void createIndex2() throws Exception {
// 1.获取client客户端对象
TransportClient client = getTransportClient();
// 2.创建实体类Blog对象,设置数据
Blog blog = new Blog();
blog.setId(3L); //long类型
blog.setTitle("跟上面创建文档的一样,内容修改。相当于覆盖,先删除原数据,再添加新数据"); //string类型
blog.setContent("跟上面创建文档的一样,内容修改。相当于覆盖,先删除原数据,再添加新数据"); //string类型
blog.setPrice(30.1f); //float类型
// 3.将对象转换json字符串
ObjectMapper objectMapper = new ObjectMapper();
String jsonData = objectMapper.writeValueAsString(blog);
// 4.封装数据,创建索引库
/*
* prepareIndex() :参数1:索引库名 参数2:type类型(表名) 参数3:索引库rows行id,不写会自动 * 生成16位码
* setSource():设置要封装发送的数据
*/
IndexResponse indexResponse = client
.prepareIndex("blog3", "article", "3")//上面的已经定义过id了,这里我们指定id,直接通过id作为条件,进行修改
.setSource(jsonData, XContentType.JSON)
.get();
// 5.关闭资源
client.close();
}
注意:这种修改的方式,是将已有的_id进行先删除,再添加了新的数据
第二种方式
@Test
public void updateIndex() throws Exception {
//1.获取client客户端对象
TransportClient client = getTransportClient();
//2.修改
Blog blog = new Blog();
blog.setId(4L);
blog.setTitle("通过调用修改api进行修改,prepareUpdate(),索引id为3的进行修改");
blog.setContent("通过调用修改api进行修改,prepareUpdate(),索引id为3的进行修改");
blog.setPrice(66f);
//3.将对象转换json字符串
ObjectMapper objectMapper = new ObjectMapper();
String jsonData = objectMapper.writeValueAsString(blog);
//4.调用修改的api,根据指定的索引id修改,传入要修改的数据,发送请求
UpdateResponse updateResponse = client.prepareUpdate("blog3", "article","3").setDoc(jsonData, XContentType.JSON).get();
//5.关闭资源
client.close();
}
Elasticsearch 删除文档
利用ElasticSearch中Java的API完成对索引的删除文档操作
-
删除索引库中的一条索引数据
@Test public void deleteData() throws Exception { //1.获取client客户端对象 TransportClient client = getTransportClient(); //2.发送删除索引库指定数据的请求 /* * client.prepareDelete("blog3", "article", "4") * 参数一:索引库(数据库) 参数二:type类型(表) 参数三:索引id(_id) */ DeleteResponse deleteResponse = client.prepareDelete("blog3", "article", "4").get(); //3.关闭资源 client.close(); } -
删除一个索引库
@Test public void deleteIndex() throws Exception { //1.获取client客户端对象 TransportClient client = getTransportClient(); //2. 删除对应名称的索引库 DeleteIndexResponse response = client.admin().indices().prepareDelete("blog3").get(); //3. 关闭资源 client.close(); }
IKAnalyzer分析器
介绍
elasticsearch搜索中文,可能并不会有你如期的效果。不过你可以在github上找一个IKAnalyzer分析器,可以解决中文语义上更好的搜索效果。
下载好后,解压到elasticsearch的plugins目录中。在plugins目录中,有一个config目录,里面是存放配置文件的,也存放着词库。可以新建词库,或者增加停顿词,扩展性高。定义好词库后,打开IKAnalyzer.cfg.xml文件,将使用的词库和停顿词库添加进去,重启es服务即可。
配置
-
打开plugins\ik\config目录,找到IKAnalyzer.cfg.xml,配置扩展词库和停顿词词库

-
修改main.dic,增加自定义的词条
大碗宽面 蓝瘦香菇 程序员 -
修改stopword.dic,增加停顿词条
and -
重启服务后,可以看到插件和配置文件已被加载

测试
IK提供了两个分词算法ik_smart 和 ik_max_word 其中 ik_smart 为最小切分,ik_max_word为最细粒度划分 :
分别来试一下
在浏览器地址栏输入下列地址
# 最小切分
http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是唱着大碗宽面and蓝瘦香菇程序员
# 最细切分
http://127.0.0.1:9200/_analyze?analyzer=ik_max_word&pretty=true&text=我是唱着大碗宽面and蓝瘦香菇的程序员
输出的结果为:
最小划分结果图,and为停顿词被忽略不分词
最细划分结果图,and为停顿词被忽略不分词,按照词库划分后,再按照最细语义划分。
Elasticsearch 配置mapping映射
意义:
不配置mapping映射,会默认创建一个无mapping的索引库
Using an IndicesAdminClient, you can create an index with all default settings and no mapping
语法举例:
CreateIndexResponse response = client.admin().indices().prepareCreate("blog").get();
解释:
无论是mapping还是映射从字面上看,都知道是产生的数据文档存储到ES内部文档的一种对应关系。这种对应关系决定了文档存储数据的准确性。只有知道了文档中每个域数据的实际存储含义,才能完成正确的存储和搜索。正如同为一个字符串,映射为全文文本(text)和关键字(keyword)有截然不同的含义。全文文本可以在分词后,被搜索查询,而关键字的功能更偏向于数据精准匹配和聚合分析。
而映射就是针对一种索引下的类型定义,同时映射的域的类型有多种:
域数据类型:
简单数据类型如 text, keyword, date, long, double, boolean or ip.(不再有string类型)
复杂对象类型如 object or nested
特殊的数据类型如 geo_point, geo_shape, or completion.
前提:
配置mapping类型映射,前提得索引库是一个空库,也就是没有任何配置、也没有数据的单纯的一个库;配置mapping只要符合这个条件就可以。(下面是创建一个库并且配置mapping的代码)
startObject:相当于一个左大括号“{”
endObject:相当于一个右大括号“}”
//创建索引库,并且给索引库定义规则。注意:被定义规则的库必须已创建并且不能有数据(也就是不能够有规则)
@Test
public void createMapping() throws Exception {
//1.获取client客户端对象
TransportClient client = getTransportClient();
//2.创建索引库,需要是一个空的库,只有空的库才能够定义规则
CreateIndexResponse response = client.admin().indices().prepareCreate("blog").get();
System.out.println("response.isShardsAcked() = " + response.isShardsAcked());
//3.判断是否创建成功
if (response.isShardsAcked()) {
//4.给创建的索引库指定规则,规则需要是json格式的数据,这里使用了分析器,并且时最小划分
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.startObject("article")
.startObject("properties")
.startObject("id").field("type", "long").field("store", true).endObject()
.startObject("title").field("type", "text").field("store", true).field("analyzer", "ik_smart").endObject()
.startObject("content").field("type", "text").field("store", true).field("analyzer", "ik_smart").endObject()
.startObject("price").field("type", "float").field("store", true).endObject()
.endObject()
.endObject()
.endObject();
//5.发送创建索引库的请求
PutMappingResponse putMappingResponse = client.admin().indices().preparePutMapping("blog")
.setType("article")
.setSource(builder)
.get();
System.out.println("putMappingResponse = " + putMappingResponse.isAcknowledged());
}
//6.关闭资源
client.close();
}
定义后的mapping对应关系图:

Elasticsearch 实现搜索
实现搜索的功能
注意:搜索前确保自己的库中有对应的数据
elasticsearch提供了很多种搜索的api,下面只列举几种常用的:
QueryBuilders.matchAllQuery():查询全部QueryBuilders.queryStringQuery(keyword):通过关键字查询QueryBuilders.termQuery("columns","property"):根据词条查询,第一个参数也就是字段名,第二个参数其实就是要查询的 “词条”QueryBuilders.idsQuery("type").addIds("_id","_id",...,"_id"):根据_id查询,根据指定的type(表)查询符合索引id的数据,索引id在es服务图形界面上是_id的形式QueryBuilders.wildcardQuery("columns","value*"):模糊查询:使用通配符查询,单字符通配符?,多字符通配符*,根据查询的词在对应的columns(字段)做查询。
QueryBuilders.matchAllQuery():查询全部
@Test
public void queryAll() throws Exception {
//1.获取client客户端对象
TransportClient client = getTransportClient();
//2.定义查询条件对象
//查询全部
QueryBuilder builder = QueryBuilders.matchAllQuery();
//3.使用client进行查询,可以查询多个索引库,跨库跨表都可以
//client.prepareSearch("blog2"):参数可以配置多个,也就是跨库
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("content") //什么都不定义的话是跨库跨表搜索,定义类型的话,是指定表的类型搜索
//.setPostFilter(QueryBuilders.rangeQuery("price").from(20f).to(30f)) setPostFilter:定义一个过滤器,将符合过滤器条件的也加入筛选条件中
//.addSort("price", SortOrder.ASC) //addSort():排序,根据指定的字段来排序
.setQuery(builder) //将上面定义好的查询条件对象放入
.get();
//4.得到查询的结果,获取命中数
SearchHits hits = searchResponse.getHits();
System.out.println("一共命中个数为:"+hits.totalHits);
//5.遍历命中数,将查询到的数据展示出来
for (SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
System.out.println(sourceAsMap.get("id"));
System.out.println(sourceAsMap.get("title"));
System.out.println(sourceAsMap.get("content"));
// System.out.println(sourceAsMap.get("price"));
System.out.println("==============================================");
}
//6.关闭资源
client.close();
}
search中还有很多链式调用的方法,大家有兴趣可以研究
QueryBuilders.queryStringQuery(keyword):通过关键字查询
@Test
public void queryAll() throws Exception {
//1.获取client客户端对象
TransportClient client = getTransportClient();
//2.定义查询条件对象
//根据多关键字搜索 :多关键词搜索使用的 一元切法
QueryBuilder builder = QueryBuilders
.queryStringQuery("我要买一本elasticsearch书籍")
.defaultField("title"); //title:在指定的字段查询,自定义
//3.使用client进行查询,可以查询多个索引库
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("content") //什么都不定义的话是跨库跨表搜索,定义类型的话,是指定表的类型搜索
//.setPostFilter(QueryBuilders.rangeQuery("price").from(20f).to(30f)) setPostFilter:定义一个过滤器,将符合过滤器条件的也加入筛选条件中
//.addSort("price", SortOrder.ASC) //addSort():排序,根据指定的字段来排序
.setQuery(builder)
.get();
//4.得到查询的结果,获取命中数
SearchHits hits = searchResponse.getHits();
System.out.println("一共命中个数为:"+hits.totalHits);
//5.遍历命中数,将查询到的数据展示出来
for (SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
System.out.println(sourceAsMap.get("id"));
System.out.println(sourceAsMap.get("title"));
System.out.println(sourceAsMap.get("content"));
// System.out.println(sourceAsMap.get("price"));
System.out.println("==============================================");
}
//6.关闭资源
client.close();
}
QueryBuilders.termQuery("columns","property"):根据词条查询
@Test
public void queryAll() throws Exception {
//1.获取client客户端对象
TransportClient client = getTransportClient();
//2.定义查询语句,根据什么字段查询
//根据词条查询,在字段title中查询含有 词条“elasticsearch”的数据
QueryBuilder builder = QueryBuilders.termQuery("title","elasticsearch");
//3.使用client进行查询,可以查询多个索引库
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("content") //什么都不定义的话是跨库跨表搜索,定义类型的话,是指定表的类型搜索
//.setPostFilter(QueryBuilders.rangeQuery("price").from(20f).to(30f)) setPostFilter:定义一个过滤器,将符合过滤器条件的也加入筛选条件中
//.addSort("price", SortOrder.ASC) //addSort():排序,根据指定的字段来排序
.setQuery(builder)
.get();
//4.得到查询的结果,获取命中数
SearchHits hits = searchResponse.getHits();
System.out.println("一共命中个数为:"+hits.totalHits);
//5.遍历命中数,将查询到的数据展示出来
for (SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
System.out.println(sourceAsMap.get("id"));
System.out.println(sourceAsMap.get("title"));
System.out.println(sourceAsMap.get("content"));
// System.out.println(sourceAsMap.get("price"));
System.out.println("==============================================");
}
//6.关闭资源
client.close();
}
QueryBuilders.idsQuery("type").addIds("_id","_id",...,"_id"):根据_id查询
@Test
public void queryAll() throws Exception {
//1.获取client客户端对象
TransportClient client = getTransportClient();
//2.定义查询语句,根据什么字段查询
//根据_id搜索,也就是根据索引 id 查询,可以传入多个id。在content表中查询id为如下的数据。
QueryBuilder builder = QueryBuilders.idsQuery("content").addIds("1","4","20");
//3.使用client进行查询,可以查询多个索引库
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("content") //什么都不定义的话是跨库跨表搜索,定义类型的话,是指定表的类型搜索
//.setPostFilter(QueryBuilders.rangeQuery("price").from(20f).to(30f)) setPostFilter:定义一个过滤器,将符合过滤器条件的也加入筛选条件中
//.addSort("price", SortOrder.ASC) //addSort():排序,根据指定的字段来排序
.setQuery(builder)
.get();
//4.得到查询的结果,获取命中数
SearchHits hits = searchResponse.getHits();
System.out.println("一共命中个数为:"+hits.totalHits);
//5.遍历命中数,将查询到的数据展示出来
for (SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
System.out.println(sourceAsMap.get("id"));
System.out.println(sourceAsMap.get("title"));
System.out.println(sourceAsMap.get("content"));
// System.out.println(sourceAsMap.get("price"));
System.out.println("==============================================");
}
//6.关闭资源
client.close();
}
QueryBuilders.wildcardQuery("columns","value*"):模糊查询
*:表示可以匹配多个字符
?:表示匹配一个字符,几个?表示匹配几个字符
@Test
public void queryAll() throws Exception {
//1.获取client客户端对象
TransportClient client = getTransportClient();
//2.定义查询语句,根据什么字段查询
//模糊搜索 query:对应的是通配符,"?"通配符只表示一个字符,"*"通配符表示多个字符
//QueryBuilder builder = QueryBuilders.wildcardQuery("title","elastic?");//查不到
QueryBuilder builder = QueryBuilders.wildcardQuery("title","elastic*");
//3.使用client进行查询,可以查询多个索引库
SearchResponse searchResponse = client.prepareSearch("blog2")
.setTypes("article") //什么都不定义的话是跨库跨表搜索,定义类型的话,是指定表的类型搜索
//.setPostFilter(QueryBuilders.rangeQuery("price").from(20f).to(30f)) setPostFilter:定义一个过滤器,将符合过滤器条件的也加入筛选条件中
//.addSort("price", SortOrder.ASC) //addSort():排序,根据指定的字段来排序
.setQuery(builder)
.get();
//4.得到查询的结果,获取命中数
SearchHits hits = searchResponse.getHits();
System.out.println("一共命中个数为:"+hits.totalHits);
//5.遍历命中数,将查询到的数据展示出来
for (SearchHit hit : hits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
System.out.println(sourceAsMap.get("id"));
System.out.println(sourceAsMap.get("title"));
System.out.println(sourceAsMap.get("content"));
// System.out.println(sourceAsMap.get("price"));
System.out.println("==============================================");
}
//6.关闭资源
client.close();
}
本文介绍了Elasticsearch,一个基于Lucene的分布式全文搜索引擎,强调了其在大数据时代的使用优势。文章详细讲解了Elasticsearch的安装、概念,如分片、复制,以及与Solr的对比。通过Java API展示了创建、修改、删除文档的操作,并提到了IKAnalyzer分析器在处理中文搜索中的作用。此外,还探讨了Elasticsearch的mapping映射配置和搜索功能的实现。




被折叠的 条评论
为什么被折叠?



