springdatajpa模糊查询_关键词搜索引擎工具

springdatajpa模糊查询_关键词搜索引擎工具1.环境搭建1.1引入依赖核心依赖如下(其他依赖自行引入)注意:springboot版本parentgroupIdorg.springframework.boot/gro

1.  环境搭建

1.1  引入依赖

核心依赖如下(其他依赖自行引入)

<!--注意:springboot版本-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.6.RELEASE</version>
</parent>

<!--springboot web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--通过spring data 操作Es-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

<!--springboot 继承test-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!--引入lombook-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.20</version>
    <scope>provided</scope>
</dependency>

注意:低版本的springboot 不支持springboot data

1.2  编写yml配置信息

    spring:
      data:
        elasticsearch:
          cluster-nodes: 172.16.251.142:9300   ##指定连接ip地址和端口号

 

2.  代码实现

2.1  创建实体类Product

@Document(indexName = "shopping",type = "product")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {

    @Id
    private String id;

    @Field(type = FieldType.Text,analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String name;

    @Field(type = FieldType.Double)
    private Double marketPrice;

    @Field(type = FieldType.Double)
    private Double shopPrice;

    @Field(type = FieldType.Text)
    private String image;

    @Field(type = FieldType.Text,analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String description;

    @Field(type = FieldType.Integer)
    private Integer isHot;

    @Field(type = FieldType.Integer)
    private Integer cId;

}


@Document: 代表一个文档记录 

​	indexName:  用来指定索引名称

​	type:		用来指定索引类型

@Id: 用来将对象中id和ES中_id映射

@Field: 用来指定ES中的字段对应Mapping

​	type: 用来指定ES中存储类型

​	analyzer: 用来指定使用哪种分词器

2.2  编写简单Repository接口类  接口中可以什么都不写使用一些基础的方法,或者根据命名规则自定义方法并实现,或者如2.3下的自定义复杂接口

/**
 * 根据需要自定义接口方法
 * 定义方法方法时需注意命名规范
 */
public interface ProductRepository extends ElasticsearchRepository<Product,String> {
}

2.3  自定义复杂方法接口CustomProductRepository及实现CustomProductRepositoryImpl

//自定义复杂方法不需要继承ElasticsearchRepository
public interface CustomProductRepository {
    //价格查询并分页
    List<Product> findByPageable(Double marketprice, Integer page,Integer size);

    //价格查询结果的总数
    Integer findByPrice(Double marketprice);

    //term查询高亮(name)
    List<Product> findByNameAndHighlightAdnPageable(String name,int page,int size);

    //term 查询结果的数量
    Integer findCountByName(String name);

    //分页查询所有
    List<Product> findAll(Integer page, Integer size);
}
@Component
public class CustomProductRepositoryImpl implements CustomProductRepository {

    //实现类需要注入elasticsearchTemplates
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;


    @Override
    //分页查所有  es默认从0页开始,JqGrid默认传的page是1,所以-1
    public List<Product> findAll(Integer page, Integer size) {
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchAllQuery())
                .withPageable(PageRequest.of(page-1, size))
                .build();
        //默认只查出来10条,不知道怎么改
        List<Product> products = elasticsearchTemplate.queryForList(searchQuery, Product.class);
        return products;
    }

    @Override
    //价格分页查询
    public List<Product> findByPageable(Double marketprice, Integer page, Integer size) {
        System.out.println(marketprice);
        NativeSearchQuery queryBuilder = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.termQuery("marketPrice", marketprice))
                .withPageable(PageRequest.of(page - 1, size)).build();
        List<Product> products = elasticsearchTemplate.queryForList(queryBuilder, Product.class);
        return products;
    }

    @Override
    //价格查询结果的总数
    public Integer findByPrice(Double marketprice) {
        NativeSearchQuery queryBuilder = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.termQuery("marketPrice", marketprice))
                .build();

        List<Product> products = elasticsearchTemplate.queryForList(queryBuilder, Product.class);
        return products.size();
    }

    @Override
    //term查询高亮(多字段查询)
    public List<Product> findByNameAndHighlightAdnPageable(String name, int page,int size) {

        HighlightBuilder.Field nameField = new HighlightBuilder
                .Field("*")
                .preTags("<span style='color:red'>")
                .postTags("</span>").requireFieldMatch(false);

        //多字段查询,可同时在name和description查询 对应实体类中的属性名
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.multiMatchQuery(name, "name", "description"))
                .withPageable(PageRequest.of(page - 1, size))
                .withHighlightFields(nameField)
                .build();

        AggregatedPage<Product> products = elasticsearchTemplate.
                queryForPage(nativeSearchQuery, Product.class, new SearchResultMapper() {
                    @Override
                    public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
                        SearchHits searchHits = response.getHits();
                        SearchHit[] hits = searchHits.getHits();
                        ArrayList<Product> products = new ArrayList<Product>();
                        for (SearchHit hit : hits) {
                            Product product = new Product();
                            //原始map
                            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                            product.setId(sourceAsMap.get("id").toString());
                            product.setName(sourceAsMap.get("name").toString());
                            product.setMarketPrice(Double.parseDouble(sourceAsMap.get("marketPrice").toString()));
                            product.setShopPrice(Double.parseDouble(sourceAsMap.get("shopPrice").toString()));
                            product.setImage(sourceAsMap.get("image").toString());
                            product.setDescription(sourceAsMap.get("description").toString());
                            //高亮
                            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                            System.out.println(highlightFields);
                            if (highlightFields.get("name") != null) {
                                String nameHighlight = highlightFields.get("name").getFragments()[0].toString();
                                product.setName(nameHighlight);
                            }
                            if (highlightFields.get("description") != null) {
                                String contentHighlight = highlightFields.get("description").getFragments()[0].toString();
                                product.setDescription(contentHighlight);
                            }
                            products.add(product);
                        }
                        return new AggregatedPageImpl<T>((List<T>) products);
                    }
                });
        return products.getContent();
    }

    @Override
    //term 高亮查询结果的数量
    public Integer findCountByName(String name) {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.multiMatchQuery(name, "name","description"))
                .build();
        return elasticsearchTemplate.queryForList(nativeSearchQuery, Product.class).size();

    }
}

2.4  Controller层实现 前提是相关数据已经存入es中,可以在添加内容的时候存进去

@RestController
@RequestMapping("product")
public class ProductController {

    @Autowired
    private ProductService productService;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private CustomProductRepository customProductRepository;

    //查所有
    @RequestMapping("findByPage")
    public Map<String,Object> findByPage(Integer rows,Integer page){
        List<Product> products = productService.findByPage(rows, page);
        //总条数
        List<Product> all = productService.findAll();
        int records = all.size();
        //总页数
        Integer total = null;
        if(records%rows == 0){
            total = records/rows;
        }else{
            total = records/rows+1;
        }
        //存入Map集合
        Map<String,Object> map =  new HashMap<>();
        map.put("rows",products);
        map.put("page",page);
        map.put("total",total);
        map.put("records",records);

        return map;
    }

    //使用es搜索
    @RequestMapping("findBySearch")
    public Map<String,Object> findBySearch(Integer rows,Integer page,String opt,String content){
        Map<String,Object> map = new HashMap<>();
        //按商品描述搜索
        if("description".equals(opt) && content != ""){
            List<Product> products = customProductRepository.findByNameAndHighlightAdnPageable(content, page, rows);
            //总数量
            Integer records = customProductRepository.findCountByName(content);
            //总页数
            Integer total = null;
            if(records % rows == 0){
                total = records/rows;
            }else{
                total = records/rows+1;
            }
            //存入map集合中
            map.put("rows",products);
            map.put("page",page);
            map.put("records",records);
            map.put("total",total);
         //按商品价格搜索
        }else if("marketPrice".equals(opt) && content != ""){
            double marketPrice = Double.parseDouble(content);
            List<Product> products = customProductRepository.findByPageable(marketPrice, page, rows);
            //总数量
            Integer records = customProductRepository.findByPrice(marketPrice);
            //总页数
            Integer total = null;
            if(records % rows == 0){
                total = records/rows;
            }else{
                total = records/rows+1;
            }
            //存入map集合中
            map.put("rows",products);
            map.put("page",page);
            map.put("records",records);
            map.put("total",total);
        }else{
            List<Product> products = customProductRepository.findAll(page, rows);
            //这样获取总数量
            long count = productRepository.count();
            int records = Math.toIntExact(count);
            //Integer records = products.size(); 这样获取的不是总数量, porducts是每次查询出来一页的数据,
            //总页数
            Integer total = null;
            if(records % rows == 0){
                total = records/rows;
            }else{
                total = records/rows+1;
            }
            //存入map集合中
            map.put("rows",products);
            map.put("page",page);
            map.put("records",records);
            map.put("total",total);
        }
        return map;
    }

}

2.5  部分前台代码

前台这里用的是BootStrap+JqGrid实现的表格

        $(function () {
            $("#sub").click(function () {
                //获取查询条件
                var opt = $("#opt").val();
                var content = $("#content").val();
                //清空表中数据
                $("#tt").jqGrid("clearGridData");
                //重新接收表中数据
                $("#tt").jqGrid("setGridParam",{
                    url:"${pageContext.request.contextPath}/product/findBySearch?opt="+opt+"&content="+content+"",
                    dataType:"json",
                    type:"post"
                }).trigger("reloadGrid");
            });
        });

注意: 搜索输入框<input type=”text”>标签,如果什么都不填,content默认的是空字符串而不是null

HTML-input文本框如果不输入任何内容提交过后是一个空字符串还是null ?

 text类型取得空字符串,radio,checkbox未选中提交则是null

 

3.效果展示

springdatajpa模糊查询_关键词搜索引擎工具

 

注意:springboot的新版本对JSP热部署配置文件的格式有所改变

老版本格式:

server:
  port: 8081
  jsp-servlet:
    init-parameters:
      development: true

新版本格式:

server:
  port: 8081
  servlet:
    jsp:
      init-parameters:
        development: true

 

刚开始学,bug比较多。

 

  详细学习文档点击这里 ——->【ES详细文档】

今天的文章springdatajpa模糊查询_关键词搜索引擎工具分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/84645.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注