Elasticsearch(五)--ES文档的操作(上)---写入文档

这篇具有很好参考价值的文章主要介绍了Elasticsearch(五)--ES文档的操作(上)---写入文档。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

使用ES构建搜索引擎时需要经常对文档进行操作,除了简单的单条文档操作,有时还需要进行批量操作。我们这章主要学习ES文档的增删改的操作,由于涉及到的代码量会比较多,所以分为3篇文章分别说明文档的这个三个操作。那么我们对文档操作的学习除了在kibana客户端之外,还会涉及到java的highLevelClient相应的操作代码。那么话不多说,我们直接开始下面的学习、

二、写入文档

2.1、单条写入文档

在ES中写入文档的请求的类型是POST,其请求形式如下:

POST /${index_name}/_doc/${_id}
{
    #写入的文档数据
}

上面的_id就是ES中的文档_id,这种请求方式是用户直接定义_id值,不使用ES自动生成的_id,请求的数据体即为写入的文档数据,格式是JSON格式。例如,在目标索引中写如下面的数据:

POST /hotel/_doc/001
{
    "name":"miss酒店1",   
    "city":"厦门",
    "price":"1145.14"
}

ES返回的结果如下:
es使用文档,elasticsearch,elasticsearch,java,spring boot
由以上结果可知,向hotel索引中写入文档成功。另外,ES在返回结果中还会显示文档的版本,这里因为文档刚刚建立,所以当前值为1.
当然,用户也可以不指定文档_id,该_id值将由ES自动生成,其请求形式如下:

POST /${index_name}/_doc
{
    #写入的文档数据
}

例如,写入上面的文档时不指定文档_id,请求的DSL如下:
es使用文档,elasticsearch,elasticsearch,java,spring boot
在Java高级REST客户端中,单条写入文档需要创建IndexRequest对象并设置对应的索引和_id字段名称,执行时调用客户端的Index()方法并把IndexRequest对象传入即可。index()方法返回IndexResponse对象,通过该对象可以获取当前请求的索引名称、文档_id和版本等。下面的代码演示了向索引中添加单条文档的方法:
首先我们需要一个Hotel实体类,

package com.mbw.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hotel {
	private String id;    //对应文档_id
	private String index; //对应索引名称
	private Float score;  //对应文档得分
	private Long version; //对应文档的版本号
	private String title; //对应索引中的title
	private String city;  //对应索引中的city
	private Double price; //对应索引中的price
}

这个实体类和前面文章讲解ES客户端那篇是一致的,包括HighLevelClient的建立等代码,这里就不做赘述了,详情大家可以回头看ES客户端的文章
然后我们建立一个ESCreateDocService,并且注入HighLevelClient:

@Service
@Slf4j
public class EsCreateDocService {
    @Autowired
	private RestHighLevelClient client;
}

那么对于单条插入文档,在Java高级REST客户端中,需要创建IndexRequest对象并设置对应的索引和_id字段名称,然后将dataMap(大家可以想像成需要创建输入的数据体)设置进IndexRequest,接着执行时调用客户端的index()方法并把IndexRequest对象传入即可,index()方法返回IndexResponse对象,通过该对象可以获取当前请求的索引名称,文档_id和版本等。下面的代码演示了向索引中添加单条文档的方法。

public Map<String, Object> singleIndexDoc(Map<String, Object> dataMap, String indexName, String indexId) throws IOException {
		IndexRequest indexRequest = new IndexRequest(indexName).id(indexId).source(dataMap);
		IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);//执行写入
		String index = indexResponse.getIndex(); //获取索引名
		String id = indexResponse.getId();  //获取文档ID
		long version = indexResponse.getVersion();  //获取文档版本
		HashMap<String, Object> resultMap = new HashMap<>();
		resultMap.put("index", index);
		resultMap.put("id", id);
		resultMap.put("version", version);
		return resultMap;
	}

然后我们创建一个controller,调用service层的方法即可,那这里之所以输入的参数传hotel,是为了不让前台输入复杂的map类型的json串,将这个json转map的操作交给后台进行。大家当然也可以将传参直接改为service层那样的传参,只不过由于参数涉及到Map,那么只能传json,表单是传不了Map类型的,所以大家一定要把service的三个参数全部放进一个类里,然后通过@RequestBody包装。

@RestController
@Slf4j
public class ESCreateController {
    @PostMapping("/create/doc")
	public FoundationResponse<Map<String, Object>> getResult(@RequestBody Hotel hotel) {
		if (hotel == null || CharSequenceUtil.isBlank(hotel.getIndex())) {
			return FoundationResponse.error(100, "参数错误");
		}
		HashMap<String, Object> dataMap = new HashMap<>();
		dataMap.put("title", hotel.getTitle());
		dataMap.put("city", hotel.getCity());
		dataMap.put("price", hotel.getPrice());
		try {
			Map<String, Object> resultMap = esCreateDocService.singleIndexDoc(dataMap, hotel.getIndex(), hotel.getId());
			return FoundationResponse.success(resultMap);
		} catch (IOException e) {
			log.warn("创建文档发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		} catch (Exception e) {
			log.error("服务发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		}
	}
}

接着到postman里验证一下:
es使用文档,elasticsearch,elasticsearch,java,spring boot
那么这里还需要拓展一个命令,它同样也可以创建文档:

POST /${index_name}/_create/${_id}
{
    #写入的文档数据
}

乍一看这个更像创建文档的命令,确实,它可以创建文档,但是它相较于_doc的创建有一种限制,比如我现在使用_doc创建一条_id已存在的记录:

POST /hotel_5/_doc/019
{
    "name":"miss酒店1",   
    "city":"厦门",
    "price":"1145.14"
}

执行后结果如下图所示,发现创建成功,但是创建不如说成是修改,也就是_doc不仅仅可以创建新的文档,它可以在_id已存在的文档基础上进行修改
es使用文档,elasticsearch,elasticsearch,java,spring boot
但是如果换成_create呢?

POST /hotel_5/_create/019
{
    "name":"miss酒店1",   
    "city":"厦门",
    "price":"1145.14"
}

执行结果如下图:发现版本冲突,也就是版本已经大于1了,说明这个文档已经存在了,那么_create命令就会失败,这是和_doc命令的区别!
es使用文档,elasticsearch,elasticsearch,java,spring boot

2.2、批量写入文档

在ES中批量写入文档的请求类型是POST,其请求类型如下:

POST /_bulk    //批量请求
{"index":{"_index":"${index_name}","_id":"${_id}"}}  //指定批量写入的请求
{...}
{"index":{"_index":"${index_name}","_id":"${_id}"}}  //设定写入的文档内容
{...}
{"index":{"_index":"${index_name}","_id":"${_id}"}}
{...}

请求体的第一行表示写入的第一条文档对应的元数据,其中,Index_name表示写入的目标索引,即写入的是哪个索引的哪个文档,第2行表示数据体,第3行表示写入的第二条文档对应的元数据,第4行表示数据体。以此类推,在一次请求里可以写入对条数据。记住,批量操作每一行代表的格式是固定的,不能不如你第一行的内容加个换行符,这样会报错,并且批量操作不允许存在换行符。下面将向hotel_order索引中批量写入3条酒店入住记录数据。

POST /_bulk
{"index":{"_index":"hotel_order","_id":"001"}}
{"username":"Mike JorDan"}
{"index":{"_index":"hotel_order","_id":"002"}}
{"username":"Tom JorDan"}
{"index":{"_index":"hotel_order","_id":"003"}}
{"username":"Kobi JorDan"}

如果你再插入的时候不指定_id,那么同前面的新增文档,_id由ES自动生成。
在实际使用过程中需要批量写入的文档比较多,有时甚至上千条或者上万条,这时如果使用Kibana的请求页面就很不方便了,一般使用Linux系统中的curl命令或者postman(Body选择binary)进行数据的批量写入。它们均支持上传文件,用户可以将批量写入的JSON数据保存到文件中,然后使用curl命令进行提交,这里我们以postman为例。
首先通过ES客户端需要进行授权,那么同之前学习Spring Security类似,我们可以通过postman中的Authorization中的Basic Auth进行授权登陆:
es使用文档,elasticsearch,elasticsearch,java,spring boot
然后点击Body中的binary上传需要批量写入的数据的JSON文件,例如本例的bulk_doc.json:
es使用文档,elasticsearch,elasticsearch,java,spring boot
文件内容如下:

{"index":{"_index":"hotel_order","_id":"001"}}
{"username":"Mike JorDan"}
{"index":{"_index":"hotel_order","_id":"002"}}
{"username":"Tom JorDan"}
{"index":{"_index":"hotel_order","_id":"003"}}
{"username":"Kobi JorDan"}

请求后,发现批量上传成功:
es使用文档,elasticsearch,elasticsearch,java,spring boot

2.3、highLevelClient批量写入文档

在Java高级REST客户端中,批量写入文档需要创建BulkRequest对象并设置对应的索引名称。对于多条预写入的文档,可构建多个IndexRequest对象并调用BulkRequest方法添加这些IndexRequest对象,执行时调用客户端的bulk()方法并把BulkRequest传入即可。bulk()方法返回BulkResponse对象,通过该对象可以获取当前请求的状态。
那么我们为了能够解耦实体类,所以需要创建一个HotelDocRequest类用来封装需要上传的属性,代码如下:

package com.mbw.pojo;

import java.util.List;
import java.util.Map;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class HotelDocRequest {
	private Hotel hotel;
	private String indexName;
	private Long indexId;
	private String docIdKey;
	private List<Hotel> hotelList;
	private List<Map<String,Object>> recordMapList;
}

然后是service层代码:

public String bulkIndexDoc(HotelDocRequest hotelDocRequest) {
		String indexName = hotelDocRequest.getIndexName();
		if (CharSequenceUtil.isBlank(indexName)) {
			throw new SearchException("索引名不能为空");
		}
		BulkRequest bulkRequest = new BulkRequest(indexName);
		List<Map<String, Object>> recordMapList = hotelDocRequest.getRecordMapList();
		for (Map<String, Object> dataMap : recordMapList) {
			//这个docIdKey代表map中值为docId对应的键值
			String docIdKey = hotelDocRequest.getDocIdKey();
			String docId = dataMap.get(docIdKey).toString();
			//这里必须每次都使用new IndexRequest(index,type),不然只会插入最后一条记录(这样插入不会覆盖已经存在的Id,也就是不能更新)
			IndexRequest indexRequest = new IndexRequest().id(docId).source(dataMap);
			//添加IndexRequest
			bulkRequest.add(indexRequest);
		}
		bulkRequest.timeout(TimeValue.timeValueSeconds(6));   //设置超时时间
		BulkResponse bulkResponse;
		try {
			bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
			if (bulkResponse.hasFailures()) {
				return "失败,原因:" + bulkResponse.buildFailureMessage();
			} else {
				return "成功";
			}
		} catch (IOException e) {
			throw new SearchException("搜索错误");
		}
	}

然后controller,在controller层我们将前端传入的hotelList转化为recordMap,这样避免了前端传入map的复杂传入,只需要写入需要上传的数据即可,类似前面的单条插入的操作:

	@PostMapping("/bulk/create/doc")
	public FoundationResponse<String> bulkIndexDoc(@RequestBody HotelDocRequest hotelDocRequest){
		List<Hotel> hotelList = hotelDocRequest.getHotelList();
		if(CollUtil.isEmpty(hotelList)){
			return FoundationResponse.error(100,"无可插入的有效文档");
		}
		//这里之所以转化是因为json输入List<Map<k,v>>这个结构非常复杂,所以由后端这边做一次转化,这样前台只需要输入List<Hotel>的json
		ArrayList<Map<String, Object>> recordListMap = new ArrayList<>();
		hotelList.forEach(hotel -> {
			HashMap<String, Object> dataMap = new HashMap<>();
			//这里对比之前的插入单条文档,需要多加入一个id
			dataMap.put("id", hotel.getId());
			dataMap.put("title", hotel.getTitle());
			dataMap.put("city", hotel.getCity());
			dataMap.put("price", hotel.getPrice());
			recordListMap.add(dataMap);
		});
		hotelDocRequest.setRecordMapList(recordListMap);
		String s = esCreateDocService.bulkIndexDoc(hotelDocRequest);
		return FoundationResponse.success(s);
	}

然后重启通过postman调用该接口,body中只需要输入hotelList即可:

{
    "hotelList": [
        {
            "id": "017",
            "title": "可莉酒店1",
            "city": "上海",
            "price": 648
        },
        {
            "id": "018",
            "title": "可莉酒店2",
            "city": "上海",
            "price": 648
        }
    ],
    "docIdKey":"id",
    "indexName":"hotel"
}

发现批量写入成功。
es使用文档,elasticsearch,elasticsearch,java,spring boot文章来源地址https://www.toymoban.com/news/detail-793166.html

到了这里,关于Elasticsearch(五)--ES文档的操作(上)---写入文档的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • elasticsearch(ES)分布式搜索引擎01——(初识ES,索引库操作和文档操作,RestClient操作索引库和文档)

    1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 1.1.2.ELK技术栈 elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域: 而elasticsearc

    2024年02月07日
    浏览(62)
  • 17、全文检索 -- Elasticsearch -- 使用 反应式 RestClient (ReactiveElasticsearchClient)操作 Es 服务器(增、删、查 :索引库和文档)

    Elasticsearch 所提供 RestHighLevelClient 本身提供了 【同步编程】 和 【异步编程】两种模型。 Elasticsearch 官方并未提供反应式的 RestClient : 因此 Spring Data Elasticsearch 额外补充了一个 ReactiveElasticsearchClient,用于提供反应式API支持, ReactiveElasticsearchClient 相当于 RestHighLevelClient 的反应式

    2024年04月28日
    浏览(49)
  • ElasticSearch基础1——索引和文档。Kibana,RestClient操作索引和文档+黑马旅游ES库导入

    导航: 【黑马Java笔记+踩坑汇总】JavaSE+JavaWeb+SSM+SpringBoot+瑞吉外卖+SpringCloud/SpringCloudAlibaba+黑马旅游+谷粒商城 黑马旅游源码:  https://wwmg.lanzouk.com/ikjTE135ybje 目录 1.初识弹性搜索elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 1.1.2.ELK弹性栈 1.1.3.elasticsearch和lucene 1.1.4.搜索引擎技术

    2024年02月01日
    浏览(56)
  • Elasticsearch学习3-使用RestClient操作es

    JavaREST客户端有两种模式: Java Low Level REST Client:ES官方的低级客户端。低级别的客户端通过http与Elasticearch集群通信。 Java High Level REST Client:ES官方的高级客户端。基于上面的低级客户端,也是通过HTTP与ES集群进行通信。它提供了更多的接口。 此外Spring也对RestClient进行了封装

    2024年02月11日
    浏览(47)
  • 项目中使用es(一):使用springboot操作elasticsearch

    写在前面 对于elasticsearch的搭建,前面写了一篇文章有简单描述如何搭建es,本次主要介绍如何在项目里使用,主要使用ElasticsearchRepository和ElasticsearchRestTemplate操作es。 搭建项目环境和选择合适版本 首先选择合适的项目组件版本,因为es版本和springboot版本有对应,如果不合适会

    2024年02月08日
    浏览(38)
  • 项目中使用es(二):使用RestHighLevelClient操作elasticsearch

    写在前面 之前写了有关elasticsearch的搭建和使用springboot操作elasticsearch,这次主要简单说下使用RestHighLevelClient工具包操作es。 搭建环境和选择合适的版本 环境还是以springboot2.7.12为基础搭建的,不过这不重要,因为这次想说的是RestHighLevelClient操作elasticsearch,RestHighLevelClient版本

    2024年02月14日
    浏览(46)
  • 【Elasticsearch】使用Python完成对ES的插入操作

    1.Python搭建Flask服务,编写ES脚本。 2.通过Java调用Python接口,完成对ES的插入操作。 Elasticsearch 7.16.0 ESObject是一个模板,其中有很多其他的函数。通过Java调用,还可以实现很多操作,如删除、查询等。

    2024年02月15日
    浏览(43)
  • 使用postman和es插件操作elasticsearch API

    本文介绍了使用postman和es浏览器插件操作elasticsearch API的常用方法 本文使用的es浏览器插件时edge下的elasticvue,可以在edge的应用商店直接搜索安装,相较于es-head,这个插件一直在维护更新,使用还是很方便的     查看索引 查看索引主要使用get方法,可以查看单个or多个索引,

    2024年02月07日
    浏览(37)
  • Elasticsearch、Kibana以及Java操作ES 的快速使用

      创建docker自定义网络 docker自定义网络可以使得 容器之间使用容器名网络互连 ,默认的网络不会有这功能。 一定要配置自定义网络,并将两个容器同时加到网络中,否则下面的 http://es:9200 会无法访问到es   启动elastic search、kibana容器 启动 elastic search容器 访问 http://192.168

    2024年02月09日
    浏览(47)
  • Elasticsearch 7.X SpringBoot 使用 ElasticsearchRestTemplate 操作 ES

    前面学习了es rest接口对es进行操作的方式,并且还学习了es的分片及扩容,有讲解了几种常见的分词器,喜欢的小伙伴可以看下本专栏的其他文章,本篇主要将 在 SpringBoot 中使用 ElasticsearchRestTemplate 对ES进行操作。 对于SpringBoot对ES的操作早在以前我就写过一篇文章,但那时基

    2023年04月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包