【ES从入门到实战】五、全文检索-ElasticSearch-入门-put&post新增数据
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【ES从入门到实战】五、全文检索-ElasticSearch-入门-put&post新增数据相关的知识,希望对你有一定的参考价值。
参考技术A 保存一个数据,保存在哪个 索引 的哪个 类型 下,指定用哪个唯一标识 PUT customer/external/1 ;在 customer 索引下的 external 类型下保存 1 号数据为
在 postman 地址栏中输入 http://192.168.56.10:9200/customer/external/1 ,使用 put 方法,输入参数体:
可以看到创建记录成功:
再一次发送请求后得到如下结果:
所以 put 方法既可以用来新增,也可以用来更新。
在 postman 中使用 post 方法发送 http://192.168.56.10:9200/customer/external/ 请求,注意没有带 id,使用的还是上面 put 方法中的参数,
可以看到创建记录成功,es 帮我们生成了一个id:
那么问题来了,put 和 post 方法有啥区别呢?如果使用 put 方法不带 id 发送请求行不行?
可以看到使用 put 方法不带 id 请求会报错,也就是说 put 是不允许不带 id 请求的,而 post 是允许的。
参考:
Elasticsearch Reference
elastic
全文搜索引擎 Elasticsearch 入门教程
五.全文检索ElasticSearch经典入门-ElasticSearch Java实战
前言
今天开始我们学习如何使用Java来操作ES,这里会讲两种操作方式,一是使用ES提供的jar包来操作,二是使用SpringBootData来操作,第二种方式是企业里面使用的较多的方式了。
Java 操作ES
环境集成
创建一个普通的Java工程,首先我们需要导入ES的jar包
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.8.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
然后创建ES的客户端
public class ESClientUtil
public static TransportClient getClient()
TransportClient client = null;
Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
try
client = new PreBuiltTransportClient(settings).addTransportAddress(
new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
catch (UnknownHostException e)
e.printStackTrace();
return client;
添加文档
编写测试类 ,往指定的索引库中添加文档
@Test
public void testAdd()
//获取客户端对象
TransportClient client = ESClientUtil.getClient();
//创建索引
IndexRequestBuilder indexRequestBuilder = client.prepareIndex("orders", "_doc", "1");
Map<String,Object> data = new HashMap<>();
data.put("id",1);
data.put("title","买了一个鼠标");
data.put("count",1);
data.put("amount",100.00);
data.put("status",1);
//获取结果
IndexResponse indexResponse = indexRequestBuilder.setSource(data).get();
//打印给过
System.out.println(indexResponse);
client.close();
打印结果如下 :
IndexResponse[index=orders,type=_doc,id=1,version=18,result=updated,seqNo=19,primaryTerm=3,shards=“total”:2,“successful”:1,“failed”:0]
获取一个文档
@Test
public void testGet()
//获取客户端对象
TransportClient client = ESClientUtil.getClient();
//获取文档
GetResponse response = client.prepareGet("orders", "_doc", "1").get();
//打印结果
System.out.println(response);
打印结果如下:amount=100.0, count=1, id=1, title=买了一个鼠标, status=1
更新一个文档
@Test
public void testUpdate()
//获取客户端对象
TransportClient client = ESClientUtil.getClient();
//修改索引
UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate("orders", "_doc", "1");
Map<String,Object> data = new HashMap<>();
data.put("id",1);
data.put("title","买了一个鼠标");
data.put("count",2);
data.put("amount",100.00);
//data.put("status",1);
//获取结果设置修改内容
UpdateResponse updateResponse = updateRequestBuilder.setDoc(data).get();
System.out.println(updateResponse);
client.close();
打印结果如下:UpdateResponse[index=orders,type=_doc,id=1,version=19,seqNo=20,primaryTerm=3,result=updated,shards=ShardInfototal=2, successful=1, failures=[]]
注意:这种修改方式是不会影响到未修改的字段的,比如上面注释掉status字段,status字段不会被修改。也就是说这种方式是局部修改。
删除一个文档
@Test
public void testDelete()
//获取客户端对象
TransportClient client = ESClientUtil.getClient();
//执行删除
DeleteResponse response = client.prepareDelete("orders", "_doc", "1").get();
//打印结果
System.out.println(response);
打印结果:DeleteResponse[index=orders,type=_doc,id=1,version=20,result=deleted,shards=ShardInfototal=2, successful=1, failures=[]]
批量操作
同时提交多个操作
@Test
public void testBuilkAdd()
//获取客户端对象
TransportClient client = ESClientUtil.getClient();
BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
Map<String,Object> data1 = new HashMap<>();
data1.put("id",1);
data1.put("title","买了一个鼠标");
data1.put("count",2);
data1.put("amount",100.00);
//添加操作
bulkRequestBuilder.add(client.prepareIndex("orders", "_doc", "1").setSource(data1));
Map<String,Object> data2 = new HashMap<>();
data2.put("id",2);
data2.put("title","买了一个鼠标");
data2.put("count",2);
data2.put("amount",100.00);
//添加操作
bulkRequestBuilder.add(client.prepareIndex("orders", "_doc", "2").setSource(data2));
Map<String,Object> data3 = new HashMap<>();
data3.put("id",2);
data3.put("title","买了一个鼠标");
data3.put("count",2);
data3.put("amount",200.00);
//修改操作
bulkRequestBuilder.add(client.prepareUpdate("orders", "_doc", "2").setDoc(data3));
BulkResponse bulkItemResponses = bulkRequestBuilder.get();
Iterator<BulkItemResponse> iterator = bulkItemResponses.iterator();
while(iterator.hasNext())
BulkItemResponse next = iterator.next();
System.out.println(next.getResponse());
client.close();
打印结果
IndexResponse[index=orders,type=_doc,id=1,version=1,result=created,seqNo=22,primaryTerm=3,shards=“total”:2,“successful”:1,“failed”:0]
IndexResponse[index=orders,type=_doc,id=2,version=4,result=updated,seqNo=3,primaryTerm=3,shards=“total”:2,“successful”:1,“failed”:0]
UpdateResponse[index=orders,type=_doc,id=2,version=5,seqNo=4,primaryTerm=3,result=updated,shards=ShardInfototal=2, successful=1, failures=[]]
DSL查询
案例:查询订单标题中包含:鼠标,价格在10-2000之间,状态为1,按照价格正排序
@Test
public void testSearch()
//获取客户端对象
TransportClient client = ESClientUtil.getClient();
SearchRequestBuilder searchRequestBuilder = client.prepareSearch("orders");
//设置分页
searchRequestBuilder.setFrom(0);
searchRequestBuilder.setSize(10);
searchRequestBuilder.addSort("amount", SortOrder.ASC);
//查询条件
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//dsl查询
List<QueryBuilder> must = boolQueryBuilder.must();
must.add(QueryBuilders.matchQuery("title" , "鼠标"));
//dsl过滤
List<QueryBuilder> filter = boolQueryBuilder.filter();
filter.add(QueryBuilders.rangeQuery("amount").lte(2000).gte(10));
filter.add(QueryBuilders.termQuery("status",1));
searchRequestBuilder.setQuery(boolQueryBuilder);
SearchResponse searchResponse = searchRequestBuilder.get();
SearchHits hits = searchResponse.getHits();
System.out.println("条数:"+hits.getTotalHits());
for (SearchHit hit : hits.getHits())
System.out.println(hit.getSourceAsMap());
client.close();
SpringBootData操作ES
环境集成
第一步:导入SpringBoot提整合ES的依赖 spring-boot-starter-data-elasticsearch
<!--SpringBoot-->
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
第二步:然后需要在yml中对ES进行配置 , 如果是集群配置增加uri即可,单个配置如下:
spring:
elasticsearch:
rest:
uris:
- http://localhost:9200
第三步:编写启动类
@SpringBootApplication
public class SearchStart
public static void main(String[] args)
SpringApplication.run(SearchStart.class);
创建Document对象
第三步:编写Document对象 ,该对象是对存储到ES中的数据的封装,同时文档映射也是通过它来实现
//标记该对象是ES的文档对象
//indexName 索引库
//type 类型
@Document(indexName = "orders",type = "_doc")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderDoc
//标记为文档ID,该ID的值会作为document的id值
@Id
private Long id;
/**
* 标题需要分词,指定为text;并使用IK分词器
* 一般需要作为关键字搜索的字段都要指定为text,因为需要分词且创建索引
*/
@Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
//@Field(type = FieldType.Keyword)
private String title;
/**
* 指定为integer类型
*/
@Field(type = FieldType.Integer)
private int count;
/**
* 状态指定为 integer类型
*/
@Field(type = FieldType.Integer)
private int status;
/**
* 金额
*/
@Field(type = FieldType.Double)
private BigDecimal amount;
创建Repository
第四步:SpringBootData提供了ElasticsearchRepository 来操作ES,该接口中包含了针对ES的CRUD方法,我们编写接口集成它即可使用
@Repository
public interface OrderRepository extends ElasticsearchRepository<OrderDoc,Long>
注意:这里的泛型是当前Repository所要管理的实体类,也就是OrderDoc,Long是实体类ID的类型
创建索引和映射
编写一个基于SpringBoot的测试类如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SearchStart.class)
public class OrderESTest
//操作ES的template模板
@Autowired
private ElasticsearchRestTemplate template;
@Autowired
private OrderRepository orderRepository;
@Test
public void test()
//创建索引
template.createIndex(CourseDoc.class);
//创建映射
template.putMapping(CourseDoc.class);
这里我注入了一个 ElasticsearchRestTemplate 工具类,通过它的 createIndex 可以创建索引库,SpringBoot指定解析 CourseDoc上的@Document注解中的index来确定索引库的名字。创建映射也是同样的道理。
基础CRUD
在SpringBoot中对ES的Crud显得极其简单,直接调用repository内置方法即可完成
@Test
public void testAdd()
orderRepository.save(new OrderDoc(1L,"买了一个表",1,1,new BigDecimal("200")));
@Test
public void testGet()
Optional<OrderDoc> optional = orderRepository.findById(1l);
System.out.println(optional.get());
@Test
public void testDelete()
orderRepository.deleteById(1L);
注意:这里并没有update方法,因为save对象的时候如果ID已经存在,就会执行update操作。repository中还有很多的方法可以使用,你可以自己去调试。
DSL查询
在SpringBoot中我们通过 NativeSearchQueryBuilder 来构建查询条件,调用repository.search来执行查询。
案例:查询标题中包含鼠标 ,状态为1,金额在10-2000之间,按照金额倒排,查询第2页数据,每页10条
@Test
public void testSearch()
//查询构建器
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
//设置分页: 第2页 (0开始), 每页10数
builder.withPageable(PageRequest.of(1,10));
//设置排序 : 金额倒排
builder.withSort(SortBuilders.fieldSort("amount").order(SortOrder.DESC));
//构建组合查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//标题包含鼠标
boolQuery.must(QueryBuilders.matchQuery("title","鼠标"))
//状态值查询
.filter(QueryBuilders.【ES从入门到实战】十七、全文检索-ElasticSearch-进阶-aggregations聚合分析
八.全文检索ElasticSearch经典入门-深入理解ElasticSearch核心原理
《从Lucene到Elasticsearch:全文检索实战》学习笔记五