国外微信叫什么| 什么是切片| 尿黄是什么原因| 核准日期是什么意思| 酒酿蛋什么时候吃效果最好| 五月初九是什么星座| 吴京和吴樾什么关系| 耳膜破了是什么感觉| 做梦吃面条是什么预兆| 肺心病是什么原因引起的| 宫颈那囊是什么| 枸杞和什么一起泡水喝最好| 舌裂是什么原因造成的| 为什么会堵奶| THENORTHFACE什么牌子| 高晓松为什么进监狱| 胸部有硬块挂什么科| 什么的陪伴| 阴道放屁是什么原因| 一直发低烧是什么原因| 早餐适合吃什么| 抑郁症吃什么药| 邪犯少阳证是什么意思| 什么防晒霜防晒效果好| 一指什么生肖| nec投影仪是什么牌子| 茄子和什么不能一起吃| 蒲公英什么时候开花| 效果图是什么意思| 心绞痛吃什么药| 安全期一般是什么时候| creative是什么意思| 胃不好吃什么菜| td什么意思| 咸池是什么意思| 一什么泪珠| 为什么吃不胖| 胃癌早期有什么症状| coolmax是什么面料| 化痰祛痰吃什么药| 头发热是什么原因| 什么是肾阴虚| lancome是什么品牌| 72年属鼠是什么命| 心脏不好吃什么水果好| 咳嗽吃什么好得快| 2028年属什么| 检查前列腺需要做什么检查| 男人跑马是什么原因| 2e是什么意思| knee是什么意思| 病理切片是什么意思| 嗜酸性粒细胞是什么| 婴儿大便隐血阳性是什么意思| 马超属什么生肖| 9月出生的是什么星座| 青霉素是什么| 脑白质脱髓鞘吃什么药| px什么意思| tv是什么意思| 第一顺位是什么意思| 牙痛是什么原因引起的| 县公安局局长是什么级别| 保胎吃什么食物好| 喝豆浆拉肚子什么原因| 青春痘长什么样| 防微杜渐什么意思| 咖色裤子配什么颜色上衣| 795是什么意思| 冷战什么意思| 血小板低是什么原因引起的| mac是什么意思啊| 奥美拉唑什么时候吃| 谷丙转氨酶偏高吃什么药| 蜂蜜加柠檬有什么功效和作用| 发际线是什么| 压榨是什么意思| 龟头炎是什么| 手指甲有月牙代表什么| 霍金什么时候去世| 幽门螺旋杆菌弱阳性是什么意思| 左甲状腺是什么病| 舌头无苔是什么原因| slf是什么意思| 阴阳人是什么意思| 10.1什么星座| 快乐是什么意思| 什么是纤维化| 陈皮是什么水果的皮| 持续高烧不退是什么原因| 捡尸是什么意思| 后背发冷发凉属于什么症状| 3月16号是什么星座| 一个土一个贝念什么| 什么是普惠性幼儿园| 胃酸反酸水吃什么药| 四不像是指什么动物| 蛋白质阳性什么意思| 五月十七是什么星座| 氏是什么意思| 肚脐是什么部位| 疤痕修复用什么药膏好| ms是什么病| 吃什么补钙快| 夸加包念什么| mice是什么意思| 前列腺是什么原因引起的| 清朝前面是什么朝代| 逆天是什么意思| 拉不出大便吃什么药| 虎牙长什么样子| 超凡脱俗是什么意思| 全托是什么意思| 春占生女是什么意思| 梦见掉牙是什么意思| 重情重义是什么意思| 乙肝复查检查什么项目| 大腿根疼挂什么科| cr是什么意思| 什么叫无氧运动| 为什么女人阴唇会变黑| 西瓜汁加什么好喝| 天蝎座和什么星座不合| 古丽是什么意思| 框镜鱼是什么鱼| 细菌性前列腺炎吃什么药| 感染hpv吃什么药| mpa是什么意思呀| 同房后小腹痛什么原因| cfp是什么证书| 眼干是什么原因| 岁月的痕迹是什么意思| 吃b族维生素有什么好处| 荔枝有什么营养| 平头哥是什么意思| 女团ace是什么意思| 免疫力差吃什么可以增强抵抗力| 吃什么升血小板快| 臭粉是什么东西| 家庭油炸用什么油好| 天可以加什么偏旁| 副科级是什么级别| 白血病有什么症状| 割痔疮后吃什么恢复快| 9月15号是什么星座| 女性排卵期出血是什么原因| 血小板计数高是什么原因| braun是什么品牌| 气血是什么意思| 染发有什么危害| 胃火旺吃什么好| 睡不着有什么好办法吗| 甲乙丙丁戊己庚辛壬癸代表什么| 早晨起床口干口苦是什么原因| 不羁放纵是什么意思| 喝什么茶减肥效果最好| 清洁度三度什么意思| 什么情况下需要做心脏造影| 心跳过快有什么危害| 左室舒张功能减低吃什么药| 什么样的红点是白血病| 硒酵母胶囊对甲状腺的作用是什么| 一什么沙发| 沉香有什么作用| 鸡汤用什么鸡| 大尾巴狼是什么意思| 什么菜| 肺寒咳嗽吃什么药| 预检是什么意思| 什么是象限| 十二指肠球炎是什么病| 下岗是什么意思| 猪肝色是什么颜色| 梦见洪水是什么意思| 知行合一是什么意思| 回流是什么意思| 虾仁和什么包饺子好吃| 雾化后为什么要漱口| 八月生日什么星座| 浮夸是什么意思| 雪人是什么生肖| 什么补蛋白最快的食物| 多发纳氏囊肿是什么意思| 血热吃什么药好得快| dha每天什么时候吃最好| 侏儒是什么意思| 儿童病毒感染吃什么药| 局部皮肤瘙痒什么原因| 看脑血管挂什么科| 切糕为什么这么贵| 保守是什么意思| 板栗不能和什么一起吃| 下腹疼是什么原因| 烟青色是什么颜色| 黑匣子是什么颜色| 吃力不讨好是什么意思| 胸部ct挂什么科| 软组织感染是什么意思| 什么是行政职务| 意象是什么意思| 肺炎挂什么科| 县团级是什么级别| 铜锣湾有什么好玩的| 精神衰弱吃什么药| 淋巴在什么位置| 梦见和别人打架是什么意思| 护理专业学什么| 做头发是什么意思| 德比什么意思| 他是什么意思| 不时之需是什么意思| 减肥不能吃什么东西| 7月11日是什么日子| 肾结石炖什么汤喝最好| 这叫什么| 榴莲苦是什么原因| 夏天能种什么菜| 肌酐激酶高是什么原因| opec是什么意思| 猪八戒的真名叫什么| 韩束属于什么档次| 发烧了吃什么药| 宫颈炎用什么药| 1946年属狗的是什么命| 什么持不什么| 肠炎吃什么药效果最好| 精神食粮是什么意思| 月朔是什么意思| 随便你是什么意思| 上火便秘吃什么药| 什么色| 工作性质是什么| 雪花秀属于什么档次| 为什么会得高血压| 空调水滴是什么模式| 发烧喝什么饮料比较好| everytime什么意思| 易主是什么意思| 医政科是做什么的| 夜卧早起是什么意思| 指甲变形是什么原因| os是什么意思| 间质性肺炎是什么意思| 飞机杯是什么意思| 脚真菌感染用什么药最好| 什么是盗汗症状| 压到蛇了是有什么预兆| 吃什么水果可以美白| 脸部出油多是什么原因| 拔智齿后要注意什么| 牙齿黑是什么原因| 儿童支气管炎吃什么药| 月经量少是什么原因| 脂蛋白高说明什么问题| 拉姆藏语什么意思| 欧皇什么意思| 右眼一直跳什么情况| 脑子萎缩是什么原因造成的| as是什么元素| 宫颈柱状上皮异位是什么意思| 甲亢适合吃什么食物| 骨化是什么意思| ibm是做什么的| 22年属什么生肖| 百度

百度 3月10日,华西都市报-封面新闻记者在外卖平台饿了么上,短时间内搜索到了不少卖香烟的小超市,不仅购买流程快捷流畅,而且没有确认和识别购买者是否成年。

Elasticsearch通用查询方案

《通用查询方案(一):开篇与基础概念》

《通用查询方案(二):QueryConditionBuilders 工具类》

《通用查询方案(三):QueryBuilderFactory 组件》

《通用查询方案(四):QueryCondition 使用指南与实战》



前言

在通用接口查询的复杂机械中,QueryBuilderFactory 宛如一台精密且强劲的核心引擎,驱动着零散的查询条件有序组合、变形,最终输出为能够精准检索数据的强大指令,为系统在数据海洋中导航。


一、QueryBuilderFactory:查询世界的 “组装大师”

QueryBuilderFactory 身负重任,其核心使命便是将一系列形态各异、语义丰富的 QueryCondition 对象,巧妙转化为适配 Elasticsearch 的 BoolQueryBuilder。无论是简单直白的单条件筛选,比如找出价格等于某个数值的商品;还是复杂到如同迷宫般多层嵌套的逻辑组合查询,像是筛选出特定时间段内发布、热门且满足多个附加条件的内容,它都能有条不紊地处理,成为连接抽象查询构思与具体数据获取的关键纽带,为业务决策提供坚如磐石的数据支持。

二、代码深度剖析

(一)buildBoolQuery 方法:指挥全局的 “调度员”

代码如下(示例):

@Component
public class QueryBuilderFactory {

    /**
     * 此方法作为构建流程的核心调度者,接收一组 QueryCondition 列表。
     * 它遍历列表,凭借条件对象的 isComposite 属性区分逻辑组合条件与普通条件,
     * 分别交予对应的处理方法,最终整合出完整的 BoolQueryBuilder,用于后续数据源查询。
     *
     * @param queryConditions 待处理的查询条件列表,涵盖各种类型的查询需求描述。
     * @return 组装完毕的 BoolQueryBuilder,可无缝对接 Elasticsearch 执行查询。
     */
    public BoolQueryBuilder buildBoolQuery(List<QueryCondition> queryConditions) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        for (QueryCondition condition : queryConditions) {
            if (condition.isComposite()) {
                boolQueryBuilder = handleCompositeCondition(boolQueryBuilder, condition);
            } else {
                boolQueryBuilder = processSingleCondition(boolQueryBuilder, condition);
            }
        }

        return boolQueryBuilder;
    }

这个方法站在构建流程的顶端,犹如一位调度经验丰富的指挥官。当传入一组 QueryCondition 列表时,它迅速开启逐一审视之旅。一旦识别出某个条件是复合条件(通过 isComposite 精准判断,像那些操作符为 MUST 或 SHOULD 且包裹着多个子条件的复杂家伙),便即刻指挥handleCompositeCondition 方法进行深度整合;若是普通的单条件,就转交给 processSingleCondition 方法细致雕琢,直至所有条件完美融入 BoolQueryBuilder 框架,输出一个完整、可用的查询构建器,随时准备奔赴数据战场。

(二)processSingleCondition 方法:雕琢细节的 “工匠”

    /**
     * 作为处理单个查询条件的专业工匠,该方法依据条件的操作符类型,
     * 运用 switch 语句打造专属的 Elasticsearch 查询构建器片段,
     * 并精准嵌入 BoolQueryBuilder 的对应位置,确保每个条件都准确表达查询语义。
     * 若遇操作符使用不当情况,果断抛出异常维护逻辑严谨性。
     *
     * @param boolQueryBuilder 已有基础的 BoolQueryBuilder,等待条件片段嵌入。
     * @param condition 单个 QueryCondition 对象,承载具体查询细节。
     * @return 更新后的 BoolQueryBuilder,融入了新的条件构建成果。
     */
    private BoolQueryBuilder processSingleCondition(BoolQueryBuilder boolQueryBuilder, QueryCondition condition) {
        switch (condition.getOperator()) {
            case EQ:
                Object eqOperand = condition.getOperand();
                boolQueryBuilder.must(QueryBuilders.termQuery(condition.getField(), eqOperand));
                break;
            case GT:
                Object gtOperand = condition.getOperand();
                boolQueryBuilder.must(QueryBuilders.rangeQuery(condition.getField()).gt(gtOperand));
                break;
            case GTE:
                Object gteOperand = condition.getOperand();
                boolQueryBuilder.must(QueryBuilders.rangeQuery(condition.getField()).gte(gteOperand));
                break;
            case LT:
                Object ltOperand = condition.getOperand();
                boolQueryBuilder.must(QueryBuilders.rangeQuery(condition.getField()).lt(ltOperand));
                break;
            case LTE:
                Object lteOperand = condition.getOperand();
                boolQueryBuilder.must(QueryBuilders.rangeQuery(condition.getField()).lte(lteOperand));
                break;
            case NOT_IN:
                List<?> notInValues = (List<?>) condition.getOperand();
                boolQueryBuilder.mustNot(QueryBuilders.termsQuery(condition.getField(), notInValues));
                break;
            case IN:
                List<?> values = (List<?>) condition.getOperand();
                boolQueryBuilder.must(QueryBuilders.termsQuery(condition.getField(), values));
                break;
            case RANGE:
                List<Object[]> rangeValues = (List<Object[]>) condition.getOperand();
                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(condition.getField());
                for (Object[] rangeValue : rangeValues) {
                    if ((boolean) rangeValue[1]) {
                        rangeQueryBuilder.gte(rangeValue[0]);
                    } else {
                        rangeQueryBuilder.gt(rangeValue[0]);
                    }
                    if ((boolean) rangeValue[3]) {
                        rangeQueryBuilder.lte(rangeValue[2]);
                    } else {
                        rangeQueryBuilder.lt(rangeValue[2]);
                    }
                }
                boolQueryBuilder.must(rangeQueryBuilder);
                break;
            case WILDCARD:
                String wildcardOperand = (String) condition.getOperand();
                boolQueryBuilder.must(QueryBuilders.wildcardQuery(condition.getField(), wildcardOperand));
                break;
            case CONTAINS:
                Object containsOperand = condition.getOperand();
                boolQueryBuilder.must(QueryBuilders.matchQuery(condition.getField(), containsOperand));
                break;
            case EXISTS:
                boolQueryBuilder.must(QueryBuilders.existsQuery(condition.getField()));
                break;
            case NESTED_EQ:
                // 处理嵌套对象的精确匹配条件
                Object[] nestedEqOperand = (Object[]) condition.getOperand();
                String nestedPath = (String) nestedEqOperand[0];
                String nestedField = (String) nestedEqOperand[1];
                Object nestedValue = nestedEqOperand[2];
                NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(nestedPath,
                        QueryBuilders.termQuery(nestedField, nestedValue));
                boolQueryBuilder.must(nestedQueryBuilder);
                break;
            case NE:
                Object neOperand = condition.getOperand();
                TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(condition.getField(), neOperand);
                boolQueryBuilder.mustNot(termQueryBuilder);
                break;
            case MUST:
            case MUST_NOT:
            case SHOULD:
                if (condition.isComposite()) {
                    boolQueryBuilder = handleCompositeCondition(boolQueryBuilder, condition);
                } else {
                    throw new IllegalArgumentException("当前条件标记不是复合条件,但使用了MUST或SHOULD操作符");
                }
                break;
            default:
                throw new IllegalArgumentException("不支持的操作符: " + condition.getOperator().getCode());
        }
        return boolQueryBuilder;
    }

此方法恰似一位专注于细节的工匠,针对不同操作符类型的单个查询条件精雕细琢。当遭遇 EQ,迅速锻造出 TermQueryBuilder,精准匹配字段值嵌入 must 子句;面对数值范围操作符,灵活构建 RangeQueryBuilder,严谨界定区间;处理集合相关的 NOT_IN 和 IN,巧妙调度 termsQuery;对于 RANGE,更是细致拆解操作数数组,精心构建起止条件完备的范围查询。一旦发现非复合条件误用 MUST 或 SHOULD,立即抛出异常,如一位严格的质检员,守护代码逻辑的纯净。

(三)handleCompositeCondition 方法:编织逻辑的 “巧匠”

    /**
     * 身为处理逻辑组合条件的大师级巧匠,该方法先拆解复合条件获取子条件列表,
     * 递归调用 processSingleCondition 雕琢每个子条件,构建子查询逻辑,
     * 最后依外层操作符(MUST 或 SHOULD)将子查询精准嫁接到主 BoolQueryBuilder。
     *
     * @param boolQueryBuilder 已有的主 BoolQueryBuilder,准备接纳子查询逻辑。
     * @param condition 表示逻辑组合条件的 QueryCondition,蕴含多层子条件。
     * @return 融入复杂逻辑组合的 BoolQueryBuilder,功能更强大完备。
     */
    private BoolQueryBuilder handleCompositeCondition(BoolQueryBuilder boolQueryBuilder, QueryCondition condition) {
        List<QueryCondition> subConditions = (List<QueryCondition>) condition.getOperand();
        BoolQueryBuilder subBoolQueryBuilder = QueryBuilders.boolQuery();
        for (QueryCondition subCondition : subConditions) {
            subBoolQueryBuilder = processSingleCondition(subBoolQueryBuilder, subCondition);
        }
        if (condition.getOperator() == OperatorEnum.MUST) {
            boolQueryBuilder.must(subBoolQueryBuilder);
        } else if (condition.getOperator() == OperatorEnum.SHOULD){
            boolQueryBuilder.should(subBoolQueryBuilder);
        }else if (condition.getOperator() == OperatorEnum.MUST_NOT){
            boolQueryBuilder.mustNot(subBoolQueryBuilder);
        }
        return boolQueryBuilder;
    }

当 buildBoolQuery 转来复合条件时,这位 “编织大师” 登场。它先是从复合条件对象中巧妙提取子条件列表,接着创建一个全新的 BoolQueryBuilder(subBoolQueryBuilder)作为临时工作间。随后,通过循环递归调用 processSingleCondition,深入剖析处理每个子条件,哪怕子条件中再嵌套复合结构,也能层层拆解、丝丝入扣地构建。最终,依据外层操作符是 MUST 还是 SHOULD,将精心编织的子查询逻辑无缝接入主 BoolQueryBuilder 对应子句,完成复杂查询逻辑的华丽嵌套,恰似搭建一座精巧复杂的逻辑积木城堡。

三、实战场景:复杂查询构建实战秀

想象构建一个社交媒体数据分析的查询,目标是找出特定网红在过去一周内发布、点赞数超 1000 且评论含热门话题标签或者提及特定合作品牌的动态。
起始,借助配套工具(假设已有 QueryConditionBuilders 等得力助手)搭建基础条件:

// 网红作者条件
QueryCondition influencerCondition = QueryConditionBuilders.create(OperatorEnum.EQ, "author", "TopInfluencer"); 
// 时间范围条件
QueryCondition timeCondition = QueryConditionBuilders.create(OperatorEnum.RANGE, "post_time", new Object[]{lastWeekStart, true, lastWeekEnd, true}); 
// 点赞数条件
QueryCondition likeCondition = QueryConditionBuilders.create(OperatorEnum.GT, "likes", 1000); 

List<QueryCondition> innerShouldConditions = new ArrayList<>();
// 话题标签条件
QueryCondition hashtagCondition = QueryConditionBuilders.create(OperatorEnum.CONTAINS, "comments", "#TrendingTopic"); 
innerShouldConditions.add(hashtagCondition);
// 品牌提及条件
QueryCondition brandCondition = QueryConditionBuilders.create(OperatorEnum.CONTAINS, "content", "PartnerBrand"); 
innerShouldConditions.add(brandCondition);

QueryCondition innerShould = QueryConditionBuilders.create(OperatorEnum.SHOULD, null, innerShouldConditions); 

List<QueryCondition> outerMustConditions = new ArrayList<>();
outerMustConditions.add(influencerCondition);
outerMustConditions.add(timeCondition);
outerMustConditions.add(likeCondition);
outerMustConditions.add(innerShould);

而后,QueryBuilderFactory 施展魔法:

BoolQueryBuilder finalQuery = QueryBuilderFactory.buildBoolQuery(outerMustConditions); 

在这段代码旅程中,先是精心构建各个基础条件,其中 innerShould 作为复合条件(SHOULD 逻辑)巧妙包裹话题和品牌条件,与其他 must 条件共同组成 outerMustConditions 列表。QueryBuilderFactory 的 buildBoolQuery 方法接手后,循环识别 innerShould 为复合条件,交予 handleCompositeCondition 处理子条件构建,其余非复合条件由 processSingleCondition 雕琢,最终融合成完整可执行查询,精准捞出目标动态,淋漓尽致地展现组件应对复杂需求的超凡实力。


总结

从接收 QueryConditionBuilders 产出的原始条件素材,到为后续 Elasticsearch 客户端呈上完美查询构建器,一气呵成。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
买什么样的老花镜好 肾结晶有什么症状 37属什么 结肠炎吃什么药 舌苔厚白应该吃什么
什么是三有保护动物 前列腺炎是什么引起的 车挂件挂什么保平安好 乳腺结节挂什么科 增强抵抗力吃什么
芬必得是什么药 可字属于五行属什么 上颚疼痛吃什么药 辣椒蟹吃什么 倒刺是什么原因引起的
生活防水是什么意思 喘息性支气管炎吃什么药 马子是什么意思 高考600多分能上什么大学 什么因果才会有双胞胎
黄芪的功效是什么hcv9jop6ns5r.cn 同房出血什么原因hcv8jop8ns2r.cn 减肥该吃什么ff14chat.com 怀孕是什么症状hcv9jop4ns8r.cn 头痛去医院挂什么科creativexi.com
什么牌子冰箱好huizhijixie.com 长孙皇后为什么叫观音婢sscsqa.com 热火朝天是什么生肖hcv7jop9ns4r.cn 犯法是什么意思kuyehao.com 螳螂是什么生肖hcv9jop1ns0r.cn
pbm是什么意思hcv7jop5ns3r.cn 去海边穿什么衣服拍照好看hcv9jop3ns8r.cn 小腹疼是什么原因hcv9jop3ns6r.cn 煜字五行属什么hcv7jop6ns3r.cn 自怨自艾什么意思hcv7jop7ns3r.cn
动员是什么意思hcv9jop5ns3r.cn 蟑螂喜欢吃什么tiangongnft.com 人老是放屁是什么原因hcv9jop5ns2r.cn psc是什么病hcv9jop2ns7r.cn 儿童办理身份证需要什么材料hcv9jop1ns4r.cn
百度