easy-es icon indicating copy to clipboard operation
easy-es copied to clipboard

混合查询getSearchSourceBuilder无法识别wrapper的排序OrderByParam的condition导致null

Open Xiamu-ssr opened this issue 10 months ago • 0 comments

问题描述

这是我的controller代码

    @PostMapping("/list")
    public EsPageInfo<CourseBase> pageList(
        @RequestBody CourseQueryBo bo
    ) {
        return courseService.pageList(bo, bo.getPageNum(), bo.getPageSize());
    }

然后是post的参数CourseQueryBo

@Data
public class CourseQueryBo implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 课程名称
     */
    private String name;

    /**
     * 大分类
     */
    private String mt;

    /**
     * 小分类
     */
    private String st;

    /**
     * 是否收费
     */
    private Boolean charge;

    /**
     * 是否热门
     */
    private Boolean isHot;


    private OrderByParam orderByParam;

    private Integer pageNum;
    private Integer pageSize;

}

当传来的参数中orderByParam不为null,但是orderByParamordersort为null。 我的Service代码如下,可以看到我的wrapper中orderBy添加了condition来保证orderByParam必需有效。

LambdaEsQueryWrapper<CourseBase> queryWrapper = new LambdaEsQueryWrapper<>();
        queryWrapper
            //大分类选择全部时,参数为空,不筛选
            .eq(StringUtils.isNotEmpty(bo.getMt()), CourseBase::getMt, bo.getMt(), CourseQueryBoostBo.mt)
            //小分类选择全部时,参数为空,不筛选
            .eq(StringUtils.isNotEmpty(bo.getSt()), CourseBase::getSt, bo.getSt(), CourseQueryBoostBo.st)
            //付费规则全选时,参数为空,不筛选
            .eq(bo.getCharge() != null, CourseBase::getCharge, bo.getCharge(), CourseQueryBoostBo.charge)
            //付费规则全选时,参数为空,不筛选
            .eq(bo.getIsHot() != null, CourseBase::getIsHot, bo.getIsHot(), CourseQueryBoostBo.isHot)
            //搜索框名称为空时,不筛选
            .match(StringUtils.isNotEmpty(bo.getName()), CourseBase::getName, bo.getName(), CourseQueryBoostBo.name)
            .orderBy(bo.getOrderByParam()!=null && bo.getOrderByParam().getOrder()!=null && bo.getOrderByParam().getSort()!=null, bo.getOrderByParam());
SearchSourceBuilder searchSourceBuilder = courseBaseMapper.getSearchSourceBuilder(queryWrapper);

然后开始debug,如图是service收到的参数,可以看到orderByParam的order和sort都是null。 image 但是却能看到wrapper中有orderByParam属性? image 随后就是进行到SearchSourceBuilder searchSourceBuilder = courseBaseMapper.getSearchSourceBuilder(queryWrapper);这一步报错,报错如下,CourseServiceImpl.java:57指的就是getSearchSourceBuilder行。

2024-04-19 14:02:28 [XNIO-1 task-18] ERROR o.d.c.s.h.GlobalExceptionHandler
 - 请求地址'/es/list',发生未知异常.
java.lang.reflect.UndeclaredThrowableException: null
	at jdk.proxy2/jdk.proxy2.$Proxy162.getSearchSourceBuilder(Unknown Source)
	at org.dromara.es.service.impl.CourseServiceImpl.pageList(CourseServiceImpl.java:57)
	at org.dromara.es.controller.CourseController.pageList(CourseController.java:58)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
Caused by: java.lang.IllegalArgumentException: fieldName must not be null
	at org.elasticsearch.search.sort.FieldSortBuilder.<init>(FieldSortBuilder.java:130)
	at org.dromara.easyes.core.core.WrapperProcessor.lambda$setSort$16(WrapperProcessor.java:449)
	at java.base/java.util.Collections$SingletonList.forEach(Collections.java:4966)
	at org.dromara.easyes.core.core.WrapperProcessor.setSort(WrapperProcessor.java:447)
	at org.dromara.easyes.core.core.WrapperProcessor.initSearchSourceBuilder(WrapperProcessor.java:332)
	at org.dromara.easyes.core.core.WrapperProcessor.buildSearchSourceBuilder(WrapperProcessor.java:61)
	at org.dromara.easyes.core.core.BaseEsMapperImpl.getSearchSourceBuilder(BaseEsMapperImpl.java:224)

有两种猜想:

  1. 可能是wrapper本身没有正确处理condition。
  2. getSearchSourceBuilder时没有正确处理condition

暂行解决方法

手动判断

LambdaEsQueryWrapper<CourseBase> queryWrapper = new LambdaEsQueryWrapper<>();
        queryWrapper
            //大分类选择全部时,参数为空,不筛选
            .eq(StringUtils.isNotEmpty(bo.getMt()), CourseBase::getMt, bo.getMt(), CourseQueryBoostBo.mt)
            //小分类选择全部时,参数为空,不筛选
            .eq(StringUtils.isNotEmpty(bo.getSt()), CourseBase::getSt, bo.getSt(), CourseQueryBoostBo.st)
            //付费规则全选时,参数为空,不筛选
            .eq(bo.getCharge() != null, CourseBase::getCharge, bo.getCharge(), CourseQueryBoostBo.charge)
            //付费规则全选时,参数为空,不筛选
            .eq(bo.getIsHot() != null, CourseBase::getIsHot, bo.getIsHot(), CourseQueryBoostBo.isHot)
            //搜索框名称为空时,不筛选
            .match(StringUtils.isNotEmpty(bo.getName()), CourseBase::getName, bo.getName(), CourseQueryBoostBo.name);

        if (bo.getOrderByParam()!=null && bo.getOrderByParam().getOrder()!=null && bo.getOrderByParam().getSort()!=null){
            //排序选择综合时,OrderByParam为空,不参与排序
            queryWrapper.orderBy(bo.getOrderByParam());
        }

Xiamu-ssr avatar Apr 19 '24 06:04 Xiamu-ssr