文章目录
-
- 环境
- 测试数据
- 增
- 删
-
- [通过`delete by api`删除](#通过
delete by api
删除) - [通过`delete by query api`删除](#通过
delete by query api
删除) - 删除索引中指定字段(script)
- [通过`delete by api`删除](#通过
- 改
-
- [单个修改`update by api`](#单个修改
update by api
) - 通过`_bulk`批量修改
- [批量修改`update by query api`](#批量修改
update by query api
) - 使用script脚本修改
- [单个修改`update by api`](#单个修改
- 查
-
- 完全匹配(term)
- 分词(match)
- 分词(match_phrase)
- [is null、空白字符](#is null、空白字符)
- 不为null,不是空白字符
- 通配符(?、*)
- 排序(sort)
- 范围查询(rangeQuery)
- must、should、filter
- 更多查询:待补充...
- 异常
环境
- elasticsearch6.8.6版本:已安装ik分词器、icu分词器、pinyin分词器(分词器版本要和es版本一致)
测试数据
测试数据使用配置了ik分词器的索引:ik_news
初始化测试数据,在测试过程中可能发生修改、新增或删除。
增
单个新增
java
@Autowired
private ElasticsearchRestTemplate restTemplate;
/*
==================================
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs.html
官网提供了java 操作api教程
*/
@Test
public void addOrUpdateOne() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
// 模拟插入的数据
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("id", 12);
dataMap.put("title", "ES客户端请求超时问题排查 - 爱定小闹钟 - 博客园");
dataMap.put("uv", 500);
dataMap.put("create_date", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
dataMap.put("status", 1);
dataMap.put("remark", "来源博客园");
// 更新请求
UpdateRequest updateRequest = new UpdateRequest(index, type, MapUtil.getStr(dataMap, "id"));
// 需要更新或插入的数据
updateRequest.doc(dataMap);
// 更新目标存在更新,不存在新增,如果不设置在找不到_id对应值的时候,直接报错
updateRequest.docAsUpsert(true);
try {
UpdateResponse updateResponse = restTemplate.getClient().update(updateRequest, RequestOptions.DEFAULT);
// 更新后数据从内存刷新到磁盘,实时刷新可能会影响性能
// restTemplate.refresh(index);
System.out.println(updateResponse);
} catch (Exception e) {
System.out.println("ES数据更新失败:" + e.getMessage());
}
}
批量新增
create_date: 字段原写错为:create_data,后来发现更正,见【删-->删除索引中指定字段】目录删除错误的字段写入。
java
@Autowired
private ElasticsearchRestTemplate restTemplate;
/*
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs-bulk.html
官网提供:批量更新示例
*/
@Test
public void addOrUpdateBatch() throws IOException {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
List<Map<String, Object>> dataList = new ArrayList<>();
// 模拟批量更新数据
// create_date: 字段原写错为:create_data,后来发现更正【见删--删除索引中指定字段】删除错误的写入。
Map<String, Object> dataMap1 = new HashMap<>();
dataMap1.put("id", 13);
dataMap1.put("title", "Es 超时设置 high-level-client_es highlevelclient-CSDN博客");
dataMap1.put("uv", 200);
dataMap1.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
dataMap1.put("status", 1);
dataMap1.put("remark", "来源CSDN博客");
Map<String, Object> dataMap2 = new HashMap<>();
dataMap2.put("id", 14);
dataMap2.put("title", "ES客户端请求超时问题排查 - 爱定小闹钟 - 博客园");
dataMap2.put("uv", 259);
dataMap2.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
dataMap2.put("status", 1);
dataMap2.put("remark", "来源博客园");
dataList.add(dataMap1);
dataList.add(dataMap2);
BulkRequest bulkRequest = new BulkRequest(index, type);
for (Map<String, Object> map : dataList) {
UpdateRequest updateRequest = new UpdateRequest(index, type, MapUtil.getStr(map, "id"));
updateRequest.doc(map);
updateRequest.docAsUpsert(true);
// 加入批量
bulkRequest.add(updateRequest);
}
try {
BulkResponse bulkResponse = restTemplate.getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
// 更新后数据从内存刷新到磁盘,实时刷新可能会影响性能
// restTemplate.refresh(index);
System.out.println(bulkResponse);
} catch (Exception e) {
System.out.println("ES数据批量更新失败:" + e.getMessage());
}
}
删
通过delete by api
删除
删除_id=8
的记录
java
@Autowired
private ElasticsearchRestTemplate restTemplate;
@Test
public void deleteOne() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
long id = 8L;
DeleteRequest deleteRequest = new DeleteRequest(index, type, Long.toString(id));
try {
DeleteResponse response = restTemplate.getClient().delete(deleteRequest, RequestOptions.DEFAULT);
System.err.println(response.getResult());
} catch (IOException e) {
e.printStackTrace();
System.out.println("删除记录失败!");
}
}
通过delete by query api
删除
删除create_date
值为null或者空字符。
条件删除一定要慎重使用,一旦查询的字段名写错,造成全查询,那就game over了。
java
@Autowired
private ElasticsearchRestTemplate restTemplate;
/**
* 通过查询条件删除
*/
@Test
public void deleteByQuery() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(index);
deleteByQueryRequest.setBatchSize(100);
deleteByQueryRequest.setDocTypes(type);
deleteByQueryRequest.setRefresh(true);
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 判断create_date为null
boolQuery.mustNot(QueryBuilders.existsQuery("create_date"));
deleteByQueryRequest.setQuery(boolQuery);
try {
restTemplate.getClient().deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
System.out.println("批量删除失败!");
}
}
删除索引中指定字段(script)
如果在添加数据的时候,字段名写错了,需要在当前索引中删除指定字段。
java客户端请求:删除索引中字段名create_data
java
@Autowired
private ElasticsearchRestTemplate restTemplate;
/*
删除索引中指定的字段
https://www.cnblogs.com/8765h/p/17318622.html
//
https://blog.csdn.net/weixin_43823808/article/details/119930308
//
https://www.yisu.com/ask/28519983.html
*/
@Test
public void deleteField() throws IOException {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
/*
mapping数据结构:
{
"properties": {
"field_1": {
"type": "keyword",
"fields": {
"keyword": {
...
}
}
}
}
}
*/
// 需要移除的字段
String[] filedNames = {"create_data"};
// 获取索引中已经存在的索引
Map<String, Object> mapping = restTemplate.getMapping(index, type);
Map properties = MapUtil.get(mapping, "properties", Map.class);
for (Object o : properties.keySet()) {
// key:索引中字段名
String key = o.toString();
// 判断需要删除的字段,是否在索引中,如果在当前索引中,删除
if (Arrays.stream(filedNames).collect(Collectors.toList()).contains(key)) {
UpdateByQueryRequest request = new UpdateByQueryRequest(index);
// 匹配文档中所有数据,需要一条一条做更新
request.setQuery(QueryBuilders.matchAllQuery());
// 把字段设置为null
// request.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source." + key + " = null", new HashMap<>()));
// 使用remove直接把字段移除
request.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.remove('" + key + "')", new HashMap<>()));
request.setBatchSize(1000);
request.setRefresh(true);
try {
BulkByScrollResponse bulkByScrollResponse = restTemplate.getClient().updateByQuery(request, RequestOptions.DEFAULT);
} catch (IOException e) {
System.err.println("删除字段错误");
}
}
}
}
改
单个修改update by api
java
@Test
public void updateOne() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
// 模拟修改的数据
// 不需要修改的字段不要写在这里,仅会对指定字段更新
Map<String, Object> dataMap = new HashMap<>();
// id找不到的记录会报错:
// Elasticsearch exception [type=document_missing_exception, reason=[_doc][122]: document missing]
dataMap.put("id", 12);
dataMap.put("title", "ES客户端请求超时问题排查 - 爱定小闹钟");
dataMap.put("uv", 520);
dataMap.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
// 写错的字段会插入到记录里面
// dataMap.put("create_data", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
// 更新请求
UpdateRequest updateRequest = new UpdateRequest(index, type, MapUtil.getStr(dataMap, "id"));
// 需要更新或插入的数据
updateRequest.doc(dataMap);
// 更新目标存在更新,不存在新增,在只允许修改的情况下这一段一定要注释掉。注释后如果修改的记录不存在会报错.
// updateRequest.docAsUpsert(true);
try {
UpdateResponse updateResponse = restTemplate.getClient().update(updateRequest, RequestOptions.DEFAULT);
// 更新后数据从内存刷新到磁盘,实时刷新可能会影响性能
// restTemplate.refresh(index);
System.out.println(updateResponse);
} catch (Exception e) {
System.out.println("ES数据更新失败:" + e.getMessage());
}
}
通过_bulk
批量修改
java
@Test
public void updateBatch() throws IOException {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
List<Map<String, Object>> dataList = new ArrayList<>();
// 模拟更新数据
Map<String, Object> dataMap1 = new HashMap<>();
dataMap1.put("id", 13);
dataMap1.put("title", "Es 超时设置 high-level-client_es highlevelclient-CSDN博客");
dataMap1.put("uv", 200);
dataMap1.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
dataMap1.put("status", 1);
dataMap1.put("remark", "来源CSDN博客");
Map<String, Object> dataMap2 = new HashMap<>();
dataMap2.put("id", 14);
dataMap2.put("title", "ES客户端请求超时问题排查 - 爱定小闹钟 - 博客园");
dataMap2.put("uv", 259);
dataMap2.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
dataMap2.put("status", null); // 设置为null
dataMap2.put("remark", null); // 设置为null
dataList.add(dataMap1);
dataList.add(dataMap2);
BulkRequest bulkRequest = new BulkRequest(index, type);
for (Map<String, Object> map : dataList) {
UpdateRequest updateRequest = new UpdateRequest(index, type, MapUtil.getStr(map, "id"));
updateRequest.doc(map);
// 更新目标存在更新,不存在新增,在只允许修改的情况下这一段一定要注释掉。注释后如果修改的记录不存在会报错.
// updateRequest.docAsUpsert(true);
// 加入批量
bulkRequest.add(updateRequest);
}
try {
BulkResponse bulkResponse = restTemplate.getClient().bulk(bulkRequest, RequestOptions.DEFAULT);
// 更新后数据从内存刷新到磁盘,实时刷新可能会影响性能
// restTemplate.refresh(index);
System.out.println(bulkResponse);
} catch (Exception e) {
System.out.println("ES数据批量更新失败:" + e.getMessage());
}
}
批量修改update by query api
【ES官网:无法对 null 值进行索引或搜索。当字段设置为 null (或空数组或值数组)时,该字段将被视为没有 null 值。】
需要注意的是,如果字段值设置为显示的null(空数组也不会被索引),那这个字段不会被es索引,所以通过某个字段=null是查不到数据的,但是可以在创建索引的时候指定null_value=NULL
进行替换:
latex
{
"settings": {
"analysis": {
"analyzer": {
"default": {
"type": "ik_max_word"
}
}
}
},
"mapping": {
"_doc": {
"properties": {
// null_value设置示例
"create_date": {
"type": "date",
"null_value": "NULL"
}
}
}
}
}
由于索引中未设置null_value
替换,所以不能查询null的值去更新了。
java
@Test
public void updateByQuery() {
// 把所有status存在的数据时间和status进行更新
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest(index);
updateByQueryRequest.setDocTypes(type);
updateByQueryRequest.setRefresh(true);
updateByQueryRequest.setBatchSize(100);
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.existsQuery("status"));
updateByQueryRequest.setQuery(boolQuery);
// 需要更新的数据
updateByQueryRequest.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.create_date = " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "", new HashMap<>()));
updateByQueryRequest.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.status = 2", new HashMap<>()));
try {
BulkByScrollResponse updatedByQuery = restTemplate.getClient().updateByQuery(updateByQueryRequest, RequestOptions.DEFAULT);
System.out.println(updatedByQuery);
} catch (IOException e) {
e.printStackTrace();
}
}
使用script脚本修改
注!使用条件查询进行更新或者删除一定要慎重,因为一旦条件写错可能会造成全查询,数据更新错误或者删除错误。
java
/**
* 通过脚本更新数据
*/
@Test
public void updateByScript() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
UpdateByQueryRequest request = new UpdateByQueryRequest(index);
// 匹配文档中所有数据,需要一条一条做更新
// 把ID为11的数据,时间更新为null,状态更新为null
request.setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("id", 11)));
// 把字段设置为null
request.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.create_date = null", new HashMap<>()));
request.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.status = null", new HashMap<>()));
request.setBatchSize(1000);
request.setDocTypes(type);
request.setRefresh(true);
try {
BulkByScrollResponse bulkByScrollResponse = restTemplate.getClient().updateByQuery(request, RequestOptions.DEFAULT);
System.out.println("更新:" + bulkByScrollResponse.getUpdated());
} catch (IOException e) {
System.err.println("更新字段错误!");
}
}
查
完全匹配(term)
java
/**
* 完全匹配查询: term进行更精准的查询匹配
*/
@Test
public void selectByBoolQueryTerm() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// text类型的字段,要term查询需要加上".keyword"
sourceBuilder.query(boolQuery.must(QueryBuilders.termQuery("title.keyword", "ES客户端请求超时问题排查 - 爱定小闹钟 - 博客园")));
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
分词(match)
java
@Test
public void selectByBoolQueryMatch() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 匹配所有包含:"三毛"、"三"、"毛"的数据
sourceBuilder.query(boolQuery.must(QueryBuilders.matchQuery("title", "三毛")));
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
分词(match_phrase)
match
和match_phrase
有什么区别?
match_phrase
可以指定分词匹配的间隔,比match
匹配更严格一些。
java
@Test
public void selectByBoolQueryMatchPhrase() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 匹配所有包含:连续在一起的"三毛"的数据
// slop指定的是分词匹配的间隔,0,代表无间隔,只能匹配到包含连续"三毛"的数据
// 匹配方式比match更严格
sourceBuilder.query(boolQuery.must(QueryBuilders.matchPhraseQuery("title", "三毛").slop(0)));
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
is null、空白字符
更新的数据见【改-->使用script脚本修改】目录。
无法查询到索引数据(null,[]无法被索引)见【改-->批量修改update by query api
】目录。
java
/**
* 布尔查询
*/
@Test
public void selectByBoolQuery() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 查询 create_date = 空
sourceBuilder.query(boolQuery.mustNot(QueryBuilders.existsQuery("create_date")));
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
不为null,不是空白字符
java
/**
* 布尔查询
*/
@Test
public void selectByBoolQuery2() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 查询 create_date is not null and status is not null
sourceBuilder.query(boolQuery.must(QueryBuilders.existsQuery("create_date")));
sourceBuilder.query(boolQuery.must(QueryBuilders.existsQuery("status")));
// sourceBuilder.query(boolQuery.mustNot(QueryBuilders.existsQuery("create_date")));
// sourceBuilder.query(boolQuery.mustNot(QueryBuilders.existsQuery("status")));
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
通配符(?、*)
java
@Test
public void selectByBoolQuery3() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 参考关于通配符的使用:https://blog.csdn.net/HiBoyljw/article/details/90747211
// 不加".keyword",会给分词,所以查不到结果了。
sourceBuilder.query(boolQuery.must(QueryBuilders.wildcardQuery("title.keyword", "*天才作家*")));
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
排序(sort)
java
@Test
public void selectByBoolQueryMatchAllSort() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 查询所有
sourceBuilder.query(QueryBuilders.matchAllQuery());
// 多条件排序可以通过设置多个sort
// 在时间升序的基础上,id升序
// 按时间升序排序
sourceBuilder.sort("create_date", SortOrder.ASC);
// 按ID升序排序
sourceBuilder.sort("id", SortOrder.ASC);
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
范围查询(rangeQuery)
java
@Test
public void selectByRangeQuery() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 范围查询 2024-01-22 <= time <= 2024-01-25
sourceBuilder.query(QueryBuilders.rangeQuery("create_date").gte("2024-01-22").lte("2024-01-25"));
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
查询结果打印:
latex
{uv=131, remark=来源网易科技, id=9, title=网易公布2022年第三季度财报|净收入|毛利润, create_date=2024-01-22, status=2}
{uv=310, remark=来源新浪财经, id=10, title=单季盈利超100亿元!比亚迪三季度毛利率超特斯拉, create_date=2024-01-23, status=2}
{uv=200, remark=来源知乎搜索, id=6, title=超全整理!三毛最出名的11本著作,没读过的一定要看看, create_date=2024-01-23, status=2}
must、should、filter
【The minimum_should_match parameter possible values】
-
must
子句(查询)必须出现在匹配的文档中,并计入分数。
-
should
子句 (query) 应出现在匹配的文档中。如果查询位于 bool 查询上下文中并且具有 must or filter 子句,则即使所有查询都不匹配,文档也会与 bool should 查询匹配。在这种情况下,这些子句仅用于影响分数。如果查询位于筛选器上下文中,或者两者都没有 must , filter 则必须至少有一个查询与文档匹配,才能使 bool 文档与 bool should 查询匹配。可以通过设置 minimum_should_match 参数来显式控制此行为。
-
filter
子句(查询)必须出现在匹配的文档中。但是,与查询的分数不同的 must 是,查询将被忽略。筛选器子句在筛选器上下文中执行,这意味着将忽略评分,并考虑将子句用于缓存。
三者聚合查询实例:
java
@Test
public void selectMustShouldFilter() {
String index = "ik_news"; // 索引名
String type = "_doc"; // 文档类型
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(index);
searchRequest.types(type);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// must必须匹配status=2
sourceBuilder.query(boolQuery.must(QueryBuilders.termQuery("status", 2))); // ok
// should至少包含n个筛选条件, 需要指定参数minimum_should_match = n
sourceBuilder.query(boolQuery.should(QueryBuilders.wildcardQuery("remark.keyword", "*百度*")));
// 设置符合must后,至少还要包含一个能匹配到should条件的参数。如果不配置此参数,should条件将不生效,设置1是在must筛选之后再匹配一遍参数
boolQuery.minimumShouldMatch(1);
// filter: 过滤uv >= 150的数据
sourceBuilder.query(boolQuery.filter(QueryBuilders.rangeQuery("uv").gte(150)));
searchRequest.source(sourceBuilder);
try {
SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
} catch (IOException e) {
e.printStackTrace();
}
}
查询结果:
latex
{uv=300, remark=来源百度知道, id=7, title=三毛的英文名为什么叫Echo?, create_date=2024-01-21, status=2}
更多查询:待补充...
待补充...
异常
执行更新操作UpdateRequest:索引中存在记录更新,不存在记录新建。
java.net.SocketTimeoutException: 30,000 milliseconds timeout on connection http-outgoing-0 [ACTIVE]
解决方式:
-
配置连接超时时间大于30s:未解决
这是从异常情况直观看到的,就是连接超时,但是具体因为什么超时的未知。
配置超时时间,这也是网上大多数给到的答案,但是没有解决我的问题。
-
先查询记录,然后再修改:未解决
同时看到网上说es有个bug,先查询,再修改就不会出现超时的错误,但是没有说的哪个版本的问题,我试了一下没有解决。
-
修改配置文件:问题解决
因为我是在windows系统上做的测试,下载es之后就直接启动了,没有对配置文件
elasticsearch.yml
做任何配置。我用postman发起http请求做测试的时候,增删改查都是成功的。但是配置Java客户端发起请求就失败了!!
Java配置:
yaml
spring:
# es连接配置
elasticsearch:
rest:
uris: 127.0.0.1:9200
username:
password:
一般,单机上.yml
需要修改几个内容:
yaml
cluster.name: master
node.name: node-1
path.data: /path/to/data
path.logs: /path/to/logs
network.host: 0.0.0.0
http.port: 9200
修改之后,重启es,重新发起更新请求,成功了!!!