数据准备
因为这篇文章是数据搜索,我们需要在我们的es服务器中插入一些数据供我们以后使用
esUserService
public interface EsUserService extends ElasticsearchRepository<User, Integer> {}
@RestControllerpublic class EsController { @Autowired private ElasticsearchRestTemplate elasticsearchTemplate; @Autowired private EsUserService esUserService; @Autowired private RestHighLevelClient client; private String[] names = {诸葛亮, "曹操", "李白", "韩信", "赵云", "小乔", 狄仁杰, "李四", “诸小明”, "王五"}; private String[] infos = {“我来自中国的一个小村庄,位于湖南省”, “我来自中国的一个叫上海的大城市,人们称之为魔都” , “我来自杭州,这是一座浪漫的城市“}; /** * 准备数据 * * @return */ @GetMapping("prepareDate") public Object saveUser() { ///添加索引mapping索引会自动创建,但mapping只使用默认,这将导致分词器无效 因此,我们手动导入mapping Random random = new Random(); List<User> users = new ArrayList<>(); for (int i = 0; i < 20; i++) { User user = new User(); user.setId(i); user.setName(names[random.nextInt(9)]); user.setAge(random.nextInt(40) + i); user.setInfo(infos[random.nextInt(2)]); users.add(user); } Iterable<User> users1 = esUserService.saveAll(users); return users1; }}
以下是我们本文的重点。
准备map转实体类因为我们需要经常使用map转对象,所以给你一个更好的map转对象方法
import java.beans.BeanInfo;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.math.BigDecimal;import java.sql.ResultSet;import java.util.Map;import java.util.Objects;/** * 将反射讲数据转化为Objectctt * * @param <T> */public class BeanHandler<T> { private Class<T> clazz; public BeanHandler(Class<T> clazz) { this.clazz = clazz; } /** * 讲sql 查询结果 Resultset转化为对象 * * @param rs * @return * @throws Exception */ public T handle(ResultSet rs) throws Exception { ///结果集默认指向第一个数据的前一个 if (rs.next()) { ///根据传入的字节码创建传入的指定对象 T obj = clazz.newInstance(); ///获取指定字节码信息 BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class); ///获取所有属性描述器 PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { ///获取结果集中对应字段名的值 Object o = rs.getObject(pd.getName()); ///执行当前方法并输入参数 pd.getWriteMethod().invoke(obj, o); } return obj; } return null; } /** * 将map 将反射转化为对象 * * @param map * @return * @throws Exception */ public T handle(Map<String, Object> map) throws Exception { ///结果集默认指向第一个数据的前一个 ///根据传入的字节码创建传入的指定对象 T obj = clazz.newInstance(); BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { Object o = map.get(pd.getName()); if (Objects.nonNull(o)) { // !!!!这里需要对属性类型进行强制性类型转换, o = getPropertyTypeObject(pd, o); // 下面的方法相当于属性 set方法 pd.getWriteMethod().invoke(obj, o); } } return obj; } /** * 将相应的mapvalue对应 强转为实体类对应的类型 * * @param pd * @param o * @return */ public Object getPropertyTypeObject(PropertyDescriptor pd, Object o) { ///当前属性类型 String name = pd.getPropertyType().getName(); name = name.substring(name.lastIndexOf(".") + 1); switch (name) { case "String": o = String.valueOf(o); break; case "Long": o = Long.valueOf(String.valueOf(o)); break; case "Double": o = Double.valueOf(String.valueOf(o)); break; case "Integer": o = Integer.valueOf(String.valueOf(o)); break; case "BigDecimal": o = new BigDecimal(String.valueOf(o)); break; } return o; }}
准确查询单个条件@PostMapping("singleConditionPreciseQuery")public Object singleConditionPreciseQuery(@RequestParam(value = "query") String query) throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.matchQuery("name", query));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// List执行请求<User> users = new ArrayList<>();SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
范围查询/** * 范围查询 * 包括from、to * * @return */@PostMapping(rangesearch1)public Object rangesearch(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.rangeQuery("age").from(from).to(to));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// ////// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}/** * 范围查询 * 不包括from、to * * @return */@PostMapping(rangesearch2)public Object rangeserch2(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.rangeQuery("age").from(from, false).to(to, false));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// ////// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}/** * 范围查询 * lt:小于,gt:大于 * * @return */@PostMapping(rangesearch3)public Object rangeserch3(@RequestParam(value = "from") int from, @RequestParam(value = "to") int to) throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.rangeQuery("age").lt(to).gt(from));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// ////// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
模糊查询支持通配符/** * 模糊查询,支持通配符 * * @return */@PostMapping("vagueSearch")public Object vagueSearch(@RequestParam(value = "query") String query) throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.wildcardQuery("name", query));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}/** * 不使用通配符的模糊查询,左右匹配 * * @return */@PostMapping(vaguesearch1)public Object vaguesearch(@RequestParam(value = "query") String query) throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.queryStringQuery(query).field("name"));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}/** * 多字段模糊查询 * * @return */@PostMapping(vaguesearch2)public Object vagueSearch2(@RequestParam(value = "query") String query) throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.multiMatchQuery(query, "name", "info"));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
排序/** * 排序 * * @return */@PostMapping("sortSearch")public Object sortSearch(@RequestParam(value = "query") String query) throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.multiMatchQuery(query, "name", "info")).sort("age", SortOrder.ASC);//按年龄顺序//搜索Searchrequestestesss searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
对文档数量进行精确统计筛选/** * 对文档数量进行精确统计筛选,降低了查询性能 * * @return */@PostMapping("countSearch")public Object countSearch() throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().trackTotalHits(true);//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// 分析查询结果returnn response;}
设置源字段过滤返回/** * 设置源字段过度考虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段 * * @return */@PostMapping("filterSearch")public Object filterSearch() throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().fetchSource(new String[]{"name", "age"}, new String[]{"id", "info"});//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
我们还可以从上图的结果中看出:
- 第一个参数结果集包括哪些字段?
- 第二个参数表示结果集不包括哪些字段
/** * 根据ID准确查询 * * @return */@PostMapping("searchByIds")public Object searchByIds(@RequestBody Map<String, Object> params) throws Exception {List<Integer> ids = (List<Integer>) params.get("ids");// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.termsQuery("_id", ids));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
matchAllQuery 搜索全部/** * matchAllQuery 搜索全部 * * @return */@PostMapping("martchAllQuery")public Object martchAllQuery() throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
match 搜索匹配/** * match 搜索匹配 * * @return */@PostMapping("martch")public Object martch(@RequestBody Map<String, Object> params) throws Exception {List<String> querys = (List<String>) params.get("querys");// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.matchQuery("name", querys));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
bool组合查询/*** match 搜索匹配** @return*/@PostMapping("martch")public Object martch(@RequestBody Map<String, Object> params) throws Exception {List<String> querys = (List<String>) params.get("querys");// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.matchQuery("name", querys));//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc"); /** * bool组合查询 * * @return */@PostMapping("boolSearch")public Object boolSearch(@RequestBody Map<String, Object> params) throws Exception {List<String> queryNames = (List<String>) params.get("names");int maxAge = (int) params.get("maxAge");int minAge = (int) params.get("minAge");// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder();BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();boolQueryBuilder.must(QueryBuilders.termsQuery("name", queryNames));boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(maxAge).gte(minAge));builder.query(boolQueryBuilder);//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
nested类型嵌套查询有时候,我们需要查询一个对象内部类
DSL的值发现通过平时的查询无法查询数据(Domain Specific language,也就是说,特定领域的特殊语言)出现了!
elasticsearch中的内部对象不能按预期工作,这里的问题是elasticsearch(lucene)使用的库没有内部对象的概念,所以内部对象被扁平化为一个简单的字段名称和值列表。
/** * nested类型嵌套查询 * * @return */@PostMapping("nestedSearch")public Object nestedSearch() throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder();//条件查询BoolQueryBuilder mainBool=new BoolQueryBuilder();mainBool.must(QueryBuilders.matchQuery("name", "赵六");//nested类型嵌套查询BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();boolQueryBuilder.must(QueryBuilders.matchQuery("user.name", "A"));boolQueryBuilder.must(QueryBuilders.matchQuery("user.info", “浦东”);NestedQueryBuilder nested = QueryBuilders.nestedQuery("user",boolQueryBuilder, ScoreMode.None);mainBool.must(nested);builder.query(mainBool);//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
多条件查询 + 排序 + 分页/** * 多条件查询 + 排序 + 分页 * * @return */@PostMapping("multiConditionSearch")public Object multiConditionSearch() throws Exception {// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder();//条件搜索BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();boolQueryBuilder.must(QueryBuilders.matchQuery("name", "张").operator(Operator.AND);//需要 满足所有字段);boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(30).gte(20));builder.query(boolQueryBuilder);//结果集成分页builder.from(0).size(2);//排序builder.sort("age",SortOrder.ASC);//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// List执行请求<User> users = new ArrayList<>();for (SearchHit searchHit : response.getHits().getHits()) {Map<String, Object> map = searchHit.getSourceAsMap();BeanHandler<User> beanHandler = new BeanHandler<>(User.class);User user = beanHandler.handle(map);users.add(user);}// 分析查询结果returnn users;}
聚合查询/** * 求和 * * @return */@PostMapping("sumSearch")public Object sumSearch() throws Exception {Map<String, Object> result = new HashMap<>();// SearchSourcebuilder创建请求 builder = new SearchSourceBuilder().query(QueryBuilders.termsQuery("_id", new int[]{1, 2, 3}));//条件搜索//结果集合分页builder.from(0).size(2);builder.query(QueryBuilders.matchAllQuery());//聚合查询AggregationBuilder aggregation = AggregationBuilders.sum("sum_age").field("age");builder.aggregation(aggregation);//搜索Searchrequestest searchRequest = new SearchRequest();searchRequest.indices("user");searchRequest.types("_doc");searchRequest.source(builder);// Searchresponse执行请求 response = client.search(searchRequest, RequestOptions.DEFAULT);// 分析查询结果returnn response;}
值得注意的是,在聚合操作的fild上,如果将该字段设置为key或text,则会出现以下错误
原因是:
文本字段没有优化每个文档字段数据(如聚合和排序)的操作,因此默认情况下禁止这些操作。
我们需要使用关键字段。或者,在设置text或key的字段上设置fieldatata=true,通过取消反转索引来加载字段数据。
请注意,这可能会占用大量内存
参考文章并稍作修改,https://blog.csdn.net/zhiyikeji/article/details/128939901