java中通过es搜索数据

这篇具有很好参考价值的文章主要介绍了java中通过es搜索数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;


@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;


//前端传递查询条件,将查询条件封装成map集合,多个条件构成map
    //返回的数据类型也是map,需要返回查询的结果,总条数之类的
    @Override
    public Map<String, Object> search(Map<String, String> searchmap) {
        //先读取到查询条件的关键字
        String keywords = searchmap.get("keywords");
        //判断关键字是否为空,不为空时再处理,为空赋初值
        if (StringUtils.isEmpty(keywords)){
            keywords = "手机";
        }

        //然后就是在es中搜索

        //1. 创建查询对象的构建对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        //2. 设置查询条件,设置前端传递的查询条件和当前实体类中的那个属性匹配查询。
        nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("title", keywords));

        //分组查询    terms("categoryGroup")是设置分组后的名字,相当于map中设置了一个键。
        //           .field("category.keyword")是匹配实体类中的要分组的字段。keyword是精确匹配
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("categoryGroup").field("category.keyword"));

        //3. 创建查询对象
        NativeSearchQuery query = nativeSearchQueryBuilder.build();

        //4. 使用es查询,查询到的所有数据都在searchHits对象中
        SearchHits<SkuInfo> searchHits = elasticsearchRestTemplate.search(query, SkuInfo.class);

        //创建一个集合用于存放分组查询的分组信息的数据
        //注:根据电视进行分词查询后可以将所有查询到的结果中的分组的字段获取出来存放进此list,所以就对应所有的数据的分类
        List<Object> categoryList = new ArrayList<>();
        //获取分组查询结果
        Terms terms = searchHits.getAggregations().get("categoryGroup");
        for (Terms.Bucket bucket : terms.getBuckets()) {
            categoryList.add(bucket.getKey());
        }

        //遍历查询结果,获取到所有查询到的数据
        List<SkuInfo> skuInfoList = new ArrayList<>();
        for (SearchHit<SkuInfo> searchHit : searchHits.getSearchHits()) {
            SkuInfo skuInfo = searchHit.getContent();
            //将查询到的skuInfo对象都存进list数组
            skuInfoList.add(skuInfo);
        }

        //map中存放查到的数据的list和总条数
        Map<String, Object> map = new HashMap<>();
        map.put("data", skuInfoList);
        map.put("dataCount", searchHits.getTotalHits());
        map.put("categoryList", categoryList);
        return map;
    }

        //map中存放查到的数据的list和总条数
        Map<String, Object> map = new HashMap<>();
        map.put("data", skuInfoList);
        map.put("dataCount", searchHits.getTotalHits());
        return map;
    }
  1. 注意
    java中通过es搜索数据
    要注意查询条件和要查询的es中的数据中的属性相匹配,具体是要查询对应数据中的那个字段

java中通过es搜索数据
在使用es查询两个参数分别是上边查询条件匹配后的查询对象和查询数据对应的实体类的字节码对象

java中通过es搜索数据
这四步就是将查询条件导入进去然后获取查询结果。

java中通过es搜索数据
这就是设置了一下,将所有条件搜索查询到的结果的数据的分类查询出来存进一个list

总结
es 查询和mybatisplus中的QueryWrapper设置条件的步骤和格式很像。mybatisplus条件查询也是先创建一个QueryWrapper对象,然后eq或like方法设置查询条件和对应要查询的实体类的字段。然后调用持久层的查询方法,将QueryWrapper对象传递进去。

补充,添加了排序,分页,条件查询等文章来源地址https://www.toymoban.com/news/detail-514219.html

//前端传递查询条件,将查询条件封装成map集合,多个条件构成map
    //返回的数据类型也是map,需要返回查询的结果,总条数之类的
    @Override
    public Map<String, Object> search(Map<String, String> searchmap) {
        //先读取到查询条件的关键字
        String keywords = searchmap.get("keywords");
        //判断关键字是否为空,不为空时再处理,为空赋初值
        if (StringUtils.isEmpty(keywords)) {
            keywords = "";
        }

        //然后就是在es中搜索
        //1. 创建查询对象的构建对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        //2. 设置查询条件,设置前端传递的查询条件和当前实体类中的那个属性匹配查询。
        nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("title", keywords));


        /*下边的分组查询就是可以获取到搜索出来的数据的一些分类,规格,品牌的统计,并不会按照输入的进行匹配查询*/
        //分类的分组查询    terms("categoryGroup")是设置分组后的名字,相当于map中设置了一个键。
        //           .field("category.keyword")是匹配实体类中的要分组的字段。keyword是精确匹配
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("categoryGroup").field("category.keyword"));

        //品牌的分组查询
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("brandGroup").field("brand.keyword"));

        //规格的分组查询
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("specGroup").field("spec.keyword"));


        /*多条件查询就是根据用户输入的数据进行匹配查询,和上边的分组查询不同,分组查询是做统计,这个是匹配用户的查询条件输出对应数据*/
        //多条件查询,即条件筛选,多条件查询时,matchQuery是自动分词查询的
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //判断条件是否为空
        if (!StringUtils.isEmpty(searchmap.get("brand"))) {
            //matchQuery的第一个参数是需要匹配的es中存入的数据字段,第二个是传递进来要匹配的字段
            boolQueryBuilder.filter(QueryBuilders.matchQuery("brand", searchmap.get("brand")));
        }
        if (!StringUtils.isEmpty(searchmap.get("category"))) {
            boolQueryBuilder.filter(QueryBuilders.matchQuery("category", searchmap.get("category")));
        }

        //规格的多条件查询,规格因为是"{\"机身内存\":\"16G\",\"网络\":\"联通4G\"}"这种格式,所以需要和其他字段区别开使用的查询方法不同
        for (String key : searchmap.keySet()) {   //前端传递进来的规格的键包括前缀spec_所以判断有包含的就是规格的
            if (key.startsWith("spec_")){
                //该方法两个参数分别是,第一个是匹配es中存入的数据的键,第二个是要进行查询的值,前端传递的查询条件
                boolQueryBuilder.filter(QueryBuilders.termQuery("specMap."+key.substring(key.indexOf("_")+1)+".keyword", searchmap.get(key)));
            }
        }

        //价格的多条件查询,先判断价格是否为空,不为空再转成double类型
        String price = searchmap.get("price");
        //价格的格式有¥-price,maxPrice-minPrice,minPrice-maxPrice,price-¥
        if (!StringUtils.isEmpty(price)){
            //将价格前后两部分切分出来
            String[] split = price.split("-");
            if ("¥".equals(split[0])) {
                //rangeQuery的方法就是判断区间的
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(Double.parseDouble(split[1])));
            }else if ("¥".equals(split[1])){
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(Double.parseDouble(split[0])));
            }else {
                //对大小值进行调换
                double minPrice = Double.parseDouble(split[0]);
                double maxPrice = Double.parseDouble(split[1]);
                if (minPrice >maxPrice){
                    double c = maxPrice;
                    maxPrice = minPrice;
                    minPrice = c;
                }
                //from -- to from是从小的to到大的
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").from(minPrice).to(maxPrice));
            }
        }

        //最后还需要把设置的条件查询的条件加入到构建对象中,进行接下来的查询对象的创建才会有结果
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        //多条件查询结束


        //分页查询
        String currentPage = searchmap.get("currentPage");
        if (StringUtils.isEmpty(currentPage)){
            currentPage = "1";
        }
        int page = Integer.parseInt(currentPage);
        //PageRequest.of的两个参数是当前页和每页显示的条数
        nativeSearchQueryBuilder.withPageable(PageRequest.of(page, 10));
        //分页查询结束


        //排序
        //sortFild是按照哪个字段进行排序
        String sortField = searchmap.get("sortField");
        //sortRule是排序规格,转成小写
        String sortRule = searchmap.get("sortRule");
        System.out.println(sortRule);
        if (!StringUtils.isEmpty(sortField) && !StringUtils.isEmpty(sortRule)) {
            sortRule = sortRule.toLowerCase();
            //.fieldSorts是判断按照哪个字段进行排序,order是传递一个排序的规则
            nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).order("asc".equals(sortRule)? SortOrder.ASC:SortOrder.DESC));
        }
        //排序结束


        //3. 创建查询对象
        NativeSearchQuery query = nativeSearchQueryBuilder.build();

        //4. 使用es查询,查询到的所有数据都在searchHits对象中
        SearchHits<SkuInfo> searchHits = elasticsearchRestTemplate.search(query, SkuInfo.class);

        //5. 处理分页结果
        SearchPage<SkuInfo> pageHits = SearchHitSupport.searchPageFor(searchHits, query.getPageable());


        //返回分页的总页数
        int pageCount = pageHits.getTotalPages();

        //获取分类的分组查询结果,es的查询结果集中放着所有的查询数据
        Terms categoryTerms = searchHits.getAggregations().get("categoryGroup");
        //创建一个集合用于存放分组查询的分组信息的数据
        //注:根据电视进行分词查询后可以将所有查询到的结果中的分组的字段获取出来存放进此list,所以就对应所有的数据的分类
        List<Object> categoryList = addGroup(categoryTerms);

        //获取品牌的分类结果
        Terms brandTerms = searchHits.getAggregations().get("brandGroup");
        List<Object> brandList = this.addGroup(brandTerms);

        //获取规格的分类结果
        Terms specTerms = searchHits.getAggregations().get("specGroup");
        List<Object> specList = this.addGroup(specTerms);   //"{\"机身内存\":\"16G\",\"网络\":\"联通4G\"}",
        Map<String, Set<String>> specMap = getSpecMap(specList);


        //遍历查询结果,获取到所有查询到的数据
        List<SkuInfo> skuInfoList = new ArrayList<>();
        for (SearchHit<SkuInfo> searchHit : searchHits.getSearchHits()) {
            SkuInfo skuInfo = searchHit.getContent();
            //将查询到的skuInfo对象都存进list数组
            skuInfoList.add(skuInfo);
        }



        //map中存放查到的数据的list和总条数
        Map<String, Object> map = new HashMap<>();
        map.put("data", skuInfoList);   //查询到的数据
        map.put("dataCount", searchHits.getTotalHits());   //数据总条数
        map.put("categoryList", categoryList);  //商品分类
        map.put("brandList", brandList);  //品牌
        map.put("specMap", specMap);   //规格
        map.put("pageCount", pageCount);   //总页数
        return map;
    }

    //此方法是通过传递进来查询到商品的规格,然后将规格处理统计后返回
    private Map<String, Set<String>> getSpecMap(List<Object> specList) {
        //需要将所有的规格转成map,而且值还要去掉重复
        Map<String, Set<String>> specMap = new HashMap<>();
        for (Object spec : specList) {
            //先将所有的规格信息转成json类型的字符创
            //再将每个规格转成map
            Map<String, String> map = JSON.parseObject(spec.toString(), Map.class);
            //读取到所有键
            Set<String> set = map.keySet();
            //根据键获取值
            for (String o : set) {  //o -> 网络
                //这是map每个键对应的值
                String s = map.get(o);  //  s -> 16G

                //如果specmap中存在o这个键,那么直接加入到o对应的值中,没有就创建set集合
                Set<String> specSet = specMap.get(o);
                //第一次循环的时候,specMap中没有键和值,所以需要创建set集合
                if (CollectionUtils.isEmpty(specSet)) {
                    specSet = new HashSet<>();
                }
                specSet.add(s);
                specMap.put(o, specSet);
            }
        }
        return specMap;
    }

    /**
     * @param terms 是传递进来一个分组的查询结果
     * @return 将传递进来的结果进行处理后装入list集合返回
     */
    private List<Object> addGroup(Terms terms) {
        List<Object> categoryList = new ArrayList<>();
        for (Terms.Bucket bucket : terms.getBuckets()) {
            categoryList.add(bucket.getKey());
        }
        return categoryList;
    }

到了这里,关于java中通过es搜索数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • es——java实现基本搜索功能

    在输入框输入搜索、点击页面过滤项、翻页、排序都会导致请求发出,查询商品信息:   需要实现的功能包括: 搜索 分类、品牌、价格过滤 排序 分页 高亮 竞价排名 接口说明:  controller层: service层: service实现类:

    2024年02月11日
    浏览(29)
  • java程序中使用ES knn搜索

    Elasticsearch 向量搜索应用介绍_es 向量检索_文晓武的博客-CSDN博客 Elasticsearch8.x KNN search 使用方式及参数介绍_elasticsearch knn_小帅毛的博客-CSDN博客 ElasticSearch的Dense Vector_elasticsearch dense vector_若石之上的博客-CSDN博客 Elastic Search : 8.0.1  RestClient restClient = RestClient.builder(          

    2024年02月12日
    浏览(39)
  • java-es 搜索条件拼接 SearchSourceBuilder

    1,根据字段数据去重 ? CollapseBuilder collapseBuilder = new CollapseBuilder(\\\"?\\\"); sourceBuilder.collapse(collapseBuilder); 2,排序 super.sourceBuilder.sort(SortBuilders. fieldSort (\\\"createTime\\\").order(SortOrder. DESC )); 3,设置搜索分页 sourceBuilder.from((searchDto.getPageIndex() - 1) * searchDto.getPageSize()).size(searchDto.getPageS

    2024年01月20日
    浏览(17)
  • Es elasticsearch 二十 站内搜索示例 高亮内容 java springboot 实现

    目录 实现思路 代码 全依赖 参数对象 搜索实现代码全代码 日志 重点 权重 分页 入参高亮数据处理 返回出参数据处理 构建请求 请求体设置搜索字段 返回数据解析获取高亮 高亮通过设置标签和class  前端设置class字体颜色 也可直接写在后端   全依赖 参数对象 搜索实现代码

    2024年02月02日
    浏览(38)
  • ES es Elasticsearch 十三 Java api 实现搜索 分页查询 复杂查询 过滤查询 ids查询 等

    目录 Java api 实现搜索 Pom.xml 建立链接 搜索全部记录 增加规则值查某些字段 搜索分页 全代码 Ids 搜索 搜索Match搜索 multi_match 搜索 多字段搜索 复杂查询 bool查询 filter  bool 复杂查询增加过滤器查询 复杂擦好像加排序 日志 思路 参考 api 写法 写Java代码 请求条件构建层次

    2024年02月04日
    浏览(49)
  • elasticsearch(ES)分布式搜索引擎04——(数据聚合,自动补全,数据同步,ES集群)

    **聚合(aggregations)**可以让我们极其方便的实现对数据的统计、分析、运算。例如: 什么品牌的手机最受欢迎? 这些手机的平均价格、最高价格、最低价格? 这些手机每月的销售情况如何? 实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近

    2024年02月08日
    浏览(39)
  • Java中通过List中的stream流去匹配相同的字段去赋值,避免for循环去查询数据库进行赋值操作

    Q :上面两个列表怎么使用流,根据equipmentDeviceMessageInfo中的phone字段去匹配userList 中的phone字段再获取userList 中是name赋值给equipmentDeviceMessageInfo 中的name。 A :以前的写法是通过for循环遍历一个一个去查询赋值,这样的话如果数据多的话一个一个遍历会查询的话肯定是很慢的,

    2024年02月07日
    浏览(38)
  • ES8 向量搜索(knn-search)java-api 实践

    官方文档-knn-search kNN搜索 k-nearest neighbor (kNN)搜索找到与查询向量最近的k个向量,如通过相似度计算。 kNN的常见用例包括: 基于自然语言处理(NLP)算法的相关性排序 产品推荐和推荐引擎 图像或视频的相似性搜索 要运行kNN搜索,您必须能够将数据转换为有意义的向量值

    2024年02月12日
    浏览(35)
  • 得物社区亿级ES数据搜索性能调优实践

    2020年以来内容标注结果搜索就是社区中后台业务的核心高频使用场景之一,为了支撑复杂的后台搜索,我们将社区内容的关键信息额外存了一份到Elasticsearch中作为二级索引使用。随着标注业务的细分、迭代和时间的推移,这个索引的文档数和搜索的RT开始逐步上升。 下面是

    2024年02月05日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包