java使用elasticsearchClient调用es7.17 – 新增数据,基本数据查询,条件筛选查询,追加条件查询

  • Post author:
  • Post category:java


当测试了es连接和对索引相关操作后,接下来我们需要针对数据进行相关简单的操作



一、新增数据

新增数据的接口只是用来测试,实际开发过程中直接通过canal同步数据即可



1、新增单条数据

	public void addOneData() throws Exception {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

//            Person p1 = new Person(1, "张三", 18, new Date());
//            Person p1 = new Person(2, "李四", 20, new Date());
            Person p1 = new Person(3, "王五", 22, new Date());

            String docId = client.index(b -> b
                    .index(indexName)
                    .id(p1.getId().toString()) //设置存储文件的id,可不设置,如不设置,es会自动分配一个id(索引要为字符串格式)
                    .document(p1)
                    .refresh(Refresh.True) // Make it visible for search
            ).id();

            System.out.println(docId);

            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("新增es单个数据失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");

    }



2、新增多条数据

	public void addBatchData() {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            Person p1 = new Person(7, "赵六2", 19, new Date());
            Person p2 = new Person(5, "孙七2", 20, new Date());
            Person p3 = new Person(6, "周八", 20, new Date());
            List<Person> personList = new ArrayList<>();
            personList.add(p1);
            personList.add(p2);

            BulkRequest.Builder br = new BulkRequest.Builder();

            //此种方式如id存在则会直接覆盖,如id不存在则会直接新增
            //如果索引不存在,则会直接新增索引
            for (Person person : personList) {
                br.operations(op -> op
                        .index(idx -> idx
                                .index(indexName)
                                .id(person.getId().toString())
                                .document(person)
                        )
                );
            }

            BulkResponse bulk = client.bulk(br.build());

            //下面方式如果设置了create,update方法,如此id存在,则添加失败。如此id不存在,则修改失败
//            BulkResponse bulk = client.bulk(_0 -> _0
//                    .operations(_1 -> _1
//                            .create(_2 -> _2
//                                    .index(indexName)
//                                    .id(p1.getId().toString())
//                                    .document(p1)
//                            ))
//                    .operations(_1 -> _1
//                            .update(_2 -> _2
//                                    .index(indexName)
//                                    .id(p3.getId().toString())
//                                    .action(_3 -> _3
//                                            .docAsUpsert(true)
//                                            .doc(p3))
//                            )
//                    )
//            );

            //每条都成功才会返回成功,有一条不成功error状态都为true
            if (bulk.errors()) {
                System.out.println("有部分数据操作失败");
                for (BulkResponseItem item : bulk.items()) {
                    if (item.error() != null) {
                        System.out.println(item.error().reason());
                    }
                }
            }

            System.out.println(JSON.toJSONString(bulk));
            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("es批量新增数据失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



二、基本数据查询



1、判断某个id的数据是否存在

	public void judgeDataIfExistById() {
		ElasticsearchClient client = null;
        String docId = "9"; //要查询的文档id
        try {
            client = this.getEsClient();

            GetResponse<Person> person = client.get(b -> b
                            .index(indexName)
                            .id(docId)
                    , Person.class
            );

            System.out.println("此id数据是否存在:" + person.found());
            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据id获取es数据失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



2、查询单索引内容

	public void getDataList() {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            SearchResponse<Person> search = client.search(b -> b
                            .index(indexName)
                    , Person.class
            );
//            long totalNum = search.hits().total().value();  //查询总条数
            List<Person> list = search.hits().hits().stream().map(p -> p.source()).collect(Collectors.toList());

            System.out.println(JSON.toJSONString(list));

            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询es列表失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



3、查询多索引内容

查询多索引内容要确保索引的实体要一样

	public void getDataListMoreIndex() {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            //此案例为同时查询存在的索引和不存在的索引
            MsearchResponse<Person> msearch = client.msearch(_0 -> _0
                            .searches(_1 -> _1
                                    .header(_3 -> _3.index(indexName))
                                    .body(_3 -> _3.query(_4 -> _4.matchAll(_5 -> _5)))
                            ).searches(_1 -> _1
                                    .header(_3 -> _3.index("non-existing"))
                                    .body(_3 -> _3.query(_4 -> _4.matchAll(_5 -> _5)))
                            )
                    , Person.class);

            System.out.println(JSON.toJSONString(msearch));
            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询es多索引内容失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



4、根据id查询内容

	public void getDataById() {
		ElasticsearchClient client = null;
        String docId = "1"; //要查询的文档id
        try {
            client = this.getEsClient();

            Person person = client.get(b -> b
                            .index(indexName)
                            .id(docId)
                    , Person.class
            ).source();

            //如果不知道返回的实体类,直接以ObjectNode接收
//            GetResponse<ObjectNode> response = client.get(g -> g
//                            .index(indexName)
//                            .id(docId),
//                    ObjectNode.class
//            );
//
//            if (response.found()) {
//                ObjectNode json = response.source();
//                String name = json.get("name").asText();
//                System.out.println("Person name " + name);
//            } else {
//                System.out.println("Person not found");
//            }

            System.out.println(JSON.toJSONString(person));
            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据id获取es数据失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



5、查询总条数

public ApiResult getAllContent() {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            SearchResponse<Map> search = client.search(b -> b
                            .index(indexName)
             				//es默认返回10000条数据,加上下面配置才能返回真正的总条数
                            .trackTotalHits(t -> t.enabled(true))
                    , Map.class
            );
            long totalNum = search.hits().total().value();  //查询总条数

            return totalNum ;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询总条数失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ApiResult.error("查询失败");
    }



三、条件筛选查询



1、字段匹配查询

筛选姓名带有 “ 三 ” 的人员信息

	public void getDataListContentOne() {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            String searchText = "三";
            SearchResponse<Person> response = client.search(s -> s
                            .index(indexName)
                            .query(q -> q
                                    .match(t -> t                   //在众多可用的查询变体中选择一个。我们在这里选择匹配查询(全文搜索)
                                            .field("name")
                                            .query(searchText)
                                    )
                            ),
                    Person.class
            );

            TotalHits total = response.hits().total();
            boolean isExactResult = total.relation() == TotalHitsRelation.Eq;

            if (isExactResult) {
                log.info("There are " + total.value() + " results");
            } else {
                log.info("There are more than " + total.value() + " results");
            }

            List<Hit<Person>> hits = response.hits().hits();
            for (Hit<Person> hit : hits) {
                Person product = hit.source();
                System.out.println("Found Person " + product.getName() + ", score " + hit.score());
            }

            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("es筛选查询失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



2、数量范围查询

筛选姓名带有“三”并且年龄大于等于18的人员信息

	public void getDataListContentTwo() {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            String searchText = "三";
            double bigAge = 18;

            //添加姓名查询条件
            Query byName = MatchQuery.of(m -> m
                    .field("name")
                    .query(searchText)
            )._toQuery();

            //添加年龄查询条件
            Query byMaxAge = RangeQuery.of(r -> r
                    .field("age")
                    .gte(JsonData.of(bigAge))       //equals:等于  gt:大于  lt:小于  gte:大于等于  lte:小于等于
            )._toQuery();

            //联合查询条件放入查询请求中
            SearchResponse<Person> response = client.search(s -> s
                            .index(indexName)
                            .query(q -> q
                                            .bool(b -> b
                                                            .filter(byName)     //filter不计算评分,效率更高。must计算评分,效率稍低
                                                            .filter(byMaxAge)
//                                            .must(byName)       //must表示匹配所有条件
//                                            .must(byMaxAge)
                                            )
                            ),
                    Person.class
            );

            List<Hit<Person>> hits = response.hits().hits();
            for (Hit<Person> hit : hits) {
                Person person = hit.source();
                System.out.println("Found person " + person.getName() + ", score " + hit.score());
            }

            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("es筛选查询失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



3、分页查询

	public void getDataListOne() {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            String searchText = "三";
            SearchResponse<Person> response = client.search(s -> s
                            .index(indexName)
                            .from(0)    //从第0条开始查
                            .size(15),  //一次查15条
                    Person.class
            );

             List<Person> list = search.hits().hits().stream().map(p -> p.source()).collect(Collectors.toList());

            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("es筛选查询失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



4、排序查询

排序和分页可以结合使用,大家根据自己需要自行组合

	public void getDataListTwo() {
		ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            SearchResponse<Person> search = client.search(b -> b
                            .index(indexName)
                            .sort(_2 -> _2
                                    .field(_3 -> _3
                                            .field("uploadTime")    //按上传时间倒序排列
                                            .order(SortOrder.Desc)))
                    , Person.class
            );
//            long totalNum = search.hits().total().value();  //查询总条数
            List<Person> list = search.hits().hits().stream().map(p -> p.source()).collect(Collectors.toList());

            System.out.println(JSON.toJSONString(list));

            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询es列表失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



四、其他需求查询



1、查询返回特定字段1

在开发过程中,不想一下子把所有字段都返回给前端,则需要指定返回特定字段,有两种方式,个人测试时第二种效率稍高,大家根据自己需要自行查看

	public void getDataListContentFour() {
		ElasticsearchClient client = null;
        try {
            client = EsUtils.getEsClient(esIp, esPort);

            SearchResponse<Map> response = client.search(_1 -> _1
                            .index(indexName)
                            .source(_2 -> _2
                                    .fetch(false))  //关闭source总字段列表
                            .fields(_2 -> _2.field("id"))   //返回特定字段值,需要多个返回值则继续追加
                            .fields(_2 -> _2.field("name"))
                            .from(0)    //从第0条开始查
                            .size(15),  //一次查15条
                    Map.class
            );
            List<Map<String, JsonData>> list = response.hits().hits().stream().map(m -> m.fields()).collect(Collectors.toList());

			//返回的格式为List<List<Map<String,List<String>>>>,要将此结构改为List<List<Map<String,String>>>
            List<HashMap<String, ? extends Serializable>> collect = list.stream().map(map ->
                    map.entrySet().stream().collect(Collectors.toMap(
                            item -> item.getKey(),
                            //返回结果如果为字符串,则会有""符号,则通过是否有""符号判断字段类型
                            item -> Optional.ofNullable(item.getValue().toJson().asJsonArray().get(0).toString().contains("\"") ?
                                    item.getValue().toJson().asJsonArray().get(0).toString().replaceAll("\"", "") :
                                    Long.valueOf(item.getValue().toJson().asJsonArray().get(0).toString())).orElse(null),
//                            item -> Optional.ofNullable(item.getValue().toJson().asJsonArray().get(0).toString().replaceAll("\"", "")).orElse(null),
                            (oldVal, currVal) -> oldVal, HashMap::new)))
                    .collect(Collectors.toList());

            System.out.println(collect);
            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("查询失败");
    }



2、查询返回特定字段2

第二种是直接source源中设置过滤的字段,也可以达到返回特定字段的效果

	public void getDataListContentFive() {
		ElasticsearchClient client = null;
        try {
            client = EsUtils.getEsClient(esIp, esPort);

            SearchResponse<Map> response = client.search(_1 -> _1
                            .index(indexName)
                            .source(_2 -> _2
                                    .filter(_3 -> _3
                                            .includes("id", "name", "age")//需要显示的字段
                                            .excludes("")))//需要排除的字段
                            .from(0)    //从第0条开始查
                            .size(15),  //一次查15条
                    Map.class
            );
            List<Map> list = response.hits().hits().stream().map(m -> m.source()).collect(Collectors.toList());

            System.out.println(list);
            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("查询失败");
    }



3、追加条件1

在开发过程中,有时候多个查询参数不是固定的,则需要根据是否有参数来判断是否需要添加查询条件,则需要实现追加参数的功能

	@Test
    public void getDatListThree() {
    	ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            SearchRequest.Builder request = new SearchRequest.Builder();
            request.index(indexName)//设置索引
                    .source(_2 -> _2
                            .filter(_3 -> _3    //设置过滤显示字段
                                    .includes("name", "age","birthday")
                                    .excludes("")))
                    .query(_2 -> _2     //查询条件一
                            .bool(_3 -> _3
                                    .must(_4 -> _4  //must为筛选匹配满足所有条件的记录
                                            .match(_5 -> _5
                                                    .field("name")
                                                    .query("张三")))
                            )
                    );

            request.query(_2 -> _2
                    .bool(_3 -> _3
                            .must(_4 -> _4      //追加筛选条件  年龄为24的记录
                                    .match(_5 -> _5
                                            .field("age")
                                            .query(18))))
            );

            SearchResponse<Map> search = client.search(request.build(), Map.class);
            List<Map> list = search.hits().hits().stream().map(m -> m.source()).collect(Collectors.toList());

            System.out.println(JSON.toJSONString(list));

            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询es列表失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



4、追加条件2

上述写法是将整个查询内容都放在外面,还有一种实现方式是生成动态query内容,其余内容按原来写法

	@Test
    public void getDatListFour() {
    	ElasticsearchClient client = null;
        try {
            client = this.getEsClient();

            BoolQuery.Builder queryBuilder = new BoolQuery.Builder();
            //添加的第一个筛选条件
            queryBuilder.must(_1 -> _1
                    .match(_2 -> _2
                            .field("name")
                            .query("张三")));

            //添加的第二个筛选条件
            queryBuilder.must(_1 -> _1
                    .match(_2 -> _2
                            .field("age")
                            .query(18)));

            SearchResponse<Map> search = client.search(_1 -> _1
                            .index(indexName)
                            .source(_2 -> _2
                                    .filter(_3 -> _3    //设置过滤显示字段
                                            .includes("name", "age", "birthday")
                                            .excludes("")))
                            .query(queryBuilder.build()._toQuery())
                            .from(0)    //从第0条开始查
                            .size(15),  //一次查15条
                    Map.class
            );

            List<Map> list = search.hits().hits().stream().map(m -> m.source()).collect(Collectors.toList());

            System.out.println(JSON.toJSONString(list));

            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询es列表失败" + e);
        } finally {
            try {
                client._transport().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("失败");
    }



版权声明:本文为qq_41444892原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。