elasticsearch java使用
本文将介绍如何使用 java 调用 elasticsearch 的 api 。
1、获取client连接
package com.test.elasticsearch; import java.net.InetAddress; import java.net.UnknownHostException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.elasticsearch.client.Client; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; /** * 抽象的Junit测试 * * @author xuwenjin */ public abstract class AbstractJunitTest { protected Logger logger = LogManager.getLogger(this.getClass()); protected Client client; /** * 获取一个客户端 */ @SuppressWarnings("resource") @Before public void getClient() throws UnknownHostException { Settings settings = Settings.builder().put("cluster.name", "xwj").build(); TransportAddress transportAddress = new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300); client = new PreBuiltTransportClient(settings).addTransportAddress(transportAddress); } /** * 关闭连接 */ @After public void close() { client.close(); } }
2、新增、删除索引
package com.test.elasticsearch; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.junit.Test; /** * 索引操作测试 * * @author xuwenjin */ public class IndexTest extends AbstractJunitTest { /** * 判断是否存在该索引 * * @param indexName * 索引名称 * @return */ public boolean isIndexExists(String indexName) { IndicesExistsRequestBuilder builder = client.admin().indices().prepareExists(indexName); IndicesExistsResponse res = builder.get(); return res.isExists(); } /** * 5.*之后,把string字段设置为了过时字段,引入text,keyword字段 * * keyword:存储数据时候,不会分词建立索引 * text:存储数据时候,会自动分词,并生成索引(这是很智能的,但在有些字段里面是没用的,所以对于有些字段使用text则浪费了空间)。 * * 如果在添加分词器的字段上,把type设置为keyword,则创建索引会失败 */ public XContentBuilder getIndexSource() throws IOException { XContentBuilder source = XContentFactory.jsonBuilder().startObject().startObject("test_type2") .startObject("properties") // code字段 .startObject("code").field("type", "text").field("index", true).field("fielddata", true).endObject() // 名称字段 .startObject("name").field("type", "keyword").field("store", false).field("index", true).endObject() // 信息字段 .startObject("info").field("type", "keyword").field("store", false).field("index", true).endObject() // 主要内容字段 .startObject("content").field("type", "text").field("store", true).field("index", true).field("analyzer", "ik_max_word").endObject() .startObject("my_title").field("type", "keyword").field("store", true).field("index", true).endObject() .startObject("you_title").field("type", "keyword").field("store", true).field("index", true).endObject() .startObject("isDelete").field("type", "boolean").field("store", true).field("index", true).endObject() .startObject("age").field("type", "long").field("store", true).field("index", true).endObject() .endObject().endObject().endObject(); return source; } /** * 创建索引 */ @Test public void createIndex() { try { if (isIndexExists("test_index2")) { logger.info("索引对象已经存在,无法创建!"); return; } CreateIndexRequestBuilder builder = client.admin().indices().prepareCreate("test_index2"); // 直接创建Map结构的setting Map<String, Object> settings = new HashMap<>(); settings.put("number_of_shards", 5); // 分片数 settings.put("number_of_replicas", 1); // 副本数 settings.put("refresh_interval", "10s"); // 刷新间隔 builder.setSettings(settings); builder.addMapping("test_type2", getIndexSource()); CreateIndexResponse res = builder.get(); logger.info(res.isAcknowledged() ? "索引创建成功!" : "索引创建失败!"); } catch (Exception e) { logger.error("创建索引失败!", e); } } /** * 删除索引 */ @Test public void deleteIndex() { try { if (!isIndexExists("test_index2")) { logger.info("索引对象已经不存在,无法删除!"); return; } DeleteIndexRequestBuilder builder = client.admin().indices().prepareDelete("test_index2"); DeleteIndexResponse res = builder.get(); logger.info(res.isAcknowledged() ? "删除索引成功!" : "删除索引失败!"); } catch (Exception e) { logger.error("删除索引失败!", e); } } }
执行createIndex方法之后,可以在elasticsearch-head中看到该索引被创建。
3、向ES中添加数据
package com.test.elasticsearch; import java.util.HashMap; import java.util.Map; import org.junit.Test; /** * 向ES中添加数据 * * @author xuwenjin */ public class AddDataTest extends AbstractJunitTest { // private static final String INDEX = "test_index1"; // private static final String TYPE = "test_type1"; private static final String INDEX2 = "test_index2"; private static final String TYPE2 = "test_type2"; @Test public void saveData() { try { Map<String, Object> source = new HashMap<String, Object>(); source.put("code", "01"); source.put("name", "科技"); source.put("info", "中共十九大"); source.put("content", "中共十九大"); source.put("my_title", "我的标题12323abcd"); source.put("you_title", "你的标题1efg"); source.put("isDelete", true); source.put("age", 16); Map<String, Object> source2 = new HashMap<String, Object>(); source2.put("code", "02"); source2.put("name", "新闻"); source2.put("info", "中国***"); source2.put("content", "中国***"); source2.put("my_title", "我的标题235325abcd"); source2.put("you_title", "你的标题346565efg"); source2.put("isDelete", false); source2.put("age", 17); Map<String, Object> source3 = new HashMap<String, Object>(); source3.put("code", "03"); source3.put("name", "科学技术"); source3.put("info", "用友建筑大武汉"); source3.put("content", "用友建筑大武汉"); source3.put("my_title", "我的标题65845abcd"); source3.put("you_title", "你的标题237678efg"); source3.put("isDelete", false); source3.put("age", 18); Map<String, Object> source4 = new HashMap<String, Object>(); source4.put("code", "04"); source4.put("name", "快手视频"); source4.put("info", "中国特色社会主义"); source4.put("content", "中国特色社会主义"); source4.put("my_title", "我的标题6789dfgf"); source4.put("you_title", "你的标题67458sdfdf"); source4.put("isDelete", true); source4.put("age", 19); Map<String, Object> source5 = new HashMap<String, Object>(); source5.put("code", "05"); source5.put("name", "科技视频"); source5.put("info", "最美天安门"); source5.put("content", "最美天安门"); source5.put("my_title", "132445dfgdfg"); source5.put("you_title", "32557fdgfg"); source5.put("isDelete", true); source5.put("age", 20); Map<String, Object> source6 = new HashMap<String, Object>(); source6.put("code", "06"); source6.put("name", "最快的技术"); source6.put("info", "美丽大武汉"); source6.put("content", "美丽大武汉"); source6.put("my_title", "356thjmkj345"); source6.put("you_title", "4gfjgfjg4523"); source6.put("isDelete", false); source6.put("age", 21); client.prepareIndex(INDEX2, TYPE2).setId("1").setSource(source).get(); client.prepareIndex(INDEX2, TYPE2).setId("2").setSource(source2).get(); client.prepareIndex(INDEX2, TYPE2).setId("3").setSource(source3).get(); client.prepareIndex(INDEX2, TYPE2).setId("4").setSource(source4).get(); client.prepareIndex(INDEX2, TYPE2).setId("5").setSource(source5).get(); client.prepareIndex(INDEX2, TYPE2).setId("6").setSource(source6).get(); } catch (Exception e) { logger.error("保存数据失败!", e); } } }
4、简单查询、删除数据
package com.test.elasticsearch; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.junit.Test; /** * 简单查询数据、删除数据 * * @author xuwenjin */ public class SimpleQueryTest extends AbstractJunitTest { private static final String INDEX = "test_index1"; // 索引 private static final String TYPE = "test_type1"; // 类型 @Test public void queryObject() { try { GetResponse res = client.prepareGet(INDEX, TYPE, "1").get(); if (res.isExists()) { logger.info("根据ID查询到数据,主要内容:" + res.getSource().get("content")); } else { logger.info("根据ID未查询到数据!"); } } catch (Exception e) { logger.error("根据ID查询记录失败!", e); } } @Test public void queryList() { try { String key = "***"; QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(key, "name", "content"); SearchResponse res = client.prepareSearch().setIndices(INDEX).setTypes(TYPE).setQuery(queryBuilder).get(); logger.info("查询到的总记录个数为:" + res.getHits().getTotalHits()); for (int i = 0; i < res.getHits().getTotalHits(); i++) { logger.info("第" + (i + 1) + "条记录主要内容为:" + res.getHits().getAt(i).getSource().get("content")); } } catch (Exception e) { logger.error("查询列表失败!", e); } } @Test public void deleteData() { try { DeleteResponse res = client.prepareDelete(INDEX, TYPE, "1").get(); logger.info("删除动作执行状态:" + res.status()); } catch (Exception e) { logger.error("删除数据失败!", e); } } }
5、复杂查询
package com.test.elasticsearch; import java.util.Map; import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.junit.Test; /** * 复杂查询,使用QueryBuilder进行bool查询 * * @author xuwenjin */ public class QueryBuilderTest extends AbstractJunitTest { private static final String INDEX2 = "test_index2"; private static final String TYPE2 = "test_type2"; public String text = "科技视频"; /** * 单个精确值查找(termQuery) */ @Test public void termQuery() { QueryBuilder queryBuilder = QueryBuilders.termQuery("code", "01"); queryBuilder = QueryBuilders.termQuery("isDelete", true); queryBuilder = QueryBuilders.termQuery("my_title", "我的标题12323abcd"); searchFunction(queryBuilder); } /** * 多个值精确查找(termsQuery) * * 一个查询相匹配的多个value */ @Test public void termsQuery() { QueryBuilder queryBuilder = QueryBuilders.termsQuery("code", "01", "03", "04"); searchFunction(queryBuilder); } /** * 查询相匹配的文档在一个范围(rangeQuery) */ @Test public void rangeQuery() { QueryBuilder queryBuilder = QueryBuilders .rangeQuery("code") // 查询code字段 .from("02") .to("04") .includeLower(true) // 包括下界 .includeUpper(false);// 不包括上界 searchFunction(queryBuilder); } /** * 查询相匹配的文档在一个范围(prefixQuery) */ @Test public void prefixQuery() { QueryBuilder queryBuilder = QueryBuilders.prefixQuery("my_title", "我的"); searchFunction(queryBuilder); } /** * 通配符检索(wildcardQuery) * * 值使用用通配符,常用于模糊查询 * * 匹配具有匹配通配符表达式( (not analyzed )的字段的文档。 支持的通配符: * *,它匹配任何字符序列(包括空字符序列) * ?,它匹配任何单个字符。 * * 请注意,此查询可能很慢,因为它需要遍历多个术语。 为了防止非常慢的通配符查询,通配符不能以任何一个通配符*或?开头。 */ @Test public void wildcardQuery() { QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("my_title", "*6789*"); queryBuilder = QueryBuilders.wildcardQuery("my_title", "*345"); queryBuilder = QueryBuilders.wildcardQuery("name", "?闻"); searchFunction(queryBuilder); } /** * 正则表达式检索(regexpQuery) 不需要^、$ */ @Test public void regexpQuery() { QueryBuilder queryBuilder = QueryBuilders.regexpQuery("my_title", "我的.+f"); searchFunction(queryBuilder); } /** * 使用模糊查询匹配文档查询(fuzzyQuery) */ @Test public void fuzzyQuery() { QueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("name", "科技"); searchFunction(queryBuilder); } /** * 类型检索(typeQuery) * * 查询该类型下的所有数据 */ @Test public void typeQuery() { QueryBuilder queryBuilder = QueryBuilders.typeQuery(TYPE2); searchFunction(queryBuilder); } /** * Ids检索, 返回指定id的全部信息 (idsQuery) * * 在idsQuery(type)方法中,也可以指定具体的类型 */ @Test public void idsQuery() { QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1", "4", "10"); searchFunction(queryBuilder); } /************************************************************ 全文检索 ************************************************************/ /** * 单个匹配 (matchQuery) * * 感觉跟termQuery效果一样 */ @Test public void matchQuery() { QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "科技"); searchFunction(queryBuilder); } /** * 查询匹配所有文件 (matchAllQuery) */ @Test public void matchAllQuery() { QueryBuilder queryBuilder = QueryBuilders.matchAllQuery(); searchFunction(queryBuilder); } /** * 匹配多个字段, field可以使用通配符(multiMatchQuery) */ @Test public void multiMatchQuery() { QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("132445dfgdfg", "my_title", "name", "you_title"); queryBuilder = QueryBuilders.multiMatchQuery("132445dfgdfg", "*title"); //字段使用通配符 searchFunction(queryBuilder); } /** * 字符串检索(queryString) * * 一个使用查询解析器解析其内容的查询。 * query_string查询提供了以简明的简写语法执行多匹配查询 multi_match queries ,布尔查询 bool queries ,提升得分 boosting ,模糊 * 匹配 fuzzy matching ,通配符 wildcards ,正则表达式 regexp 和范围查询 range queries 的方式。 * * 支持参数达10几种 */ @Test public void queryString() { QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("*技术"); //通配符查询 // QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("我的.+f"); searchFunction(queryBuilder); } /** * must 相当于and,就是都满足 * should 相当于or,满足一个或多个 * must_not 都不满足 */ @Test public void testQueryBuilder2() { // "科技视频"分词的结果是"科技", "视频", "频" BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); // queryBuilder.must(QueryBuilders.wildcardQuery("name", "*科技*")); // queryBuilder.must(QueryBuilders.wildcardQuery("info", "*共*")); // queryBuilder.must(QueryBuilders.wildcardQuery("content", "*美丽*")); queryBuilder.should(QueryBuilders.wildcardQuery("name", "*科技*")); queryBuilder.should(QueryBuilders.wildcardQuery("info", "*共*")); queryBuilder.should(QueryBuilders.wildcardQuery("content", "*美丽*")); queryBuilder.minimumShouldMatch(2); // 最少匹配数 // queryBuilder.mustNot(QueryBuilders.wildcardQuery("name", "*科技*")); // queryBuilder.mustNot(QueryBuilders.wildcardQuery("info", "*共*")); // queryBuilder.mustNot(QueryBuilders.wildcardQuery("content", "*美丽*")); searchFunction(queryBuilder); } /** * 查询遍历抽取 * * 查询结果是根据分值排序(从大到小) * * @param queryBuilder */ private void searchFunction(QueryBuilder queryBuilder) { SearchRequestBuilder requestBuilder = client.prepareSearch().setIndices(INDEX2).setTypes(TYPE2) .setScroll(new TimeValue(60000)).setQuery(queryBuilder); SearchResponse response = requestBuilder.setFrom(0).setSize(100).execute().actionGet(); System.out.println("--------------查询结果:----------------------"); for (SearchHit hit : response.getHits()) { System.out.println("分值:" + hit.getScore()); // 相关度 Map<String, Object> map = hit.getSource(); for (String sKey : map.keySet()) { System.out.println(sKey + ": " + map.get(sKey)); } System.out.println("--------------"); } System.out.println("-----------------------------------"); } }
本文的源码地址:https://github.com/xuwenjin/xwj_repo/tree/master/elasticsearch
参考资料:
解析Elasticsearch的SearchRequestBuilder的query类型
知识改变世界
分类:
ElasticSearch
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了