基于Lucene实现费率卡关联产品的日期与价格范围查询方案咨询
基于Lucene的可行方案
针对你的产品费率动态变动场景,结合订单日期筛选、价格范围过滤及价格排序需求,以下是几种基于Lucene的实现方案:
方案一:预计算常见订单周期的价格并索引
针对酒店类常见的短期订单场景,提前预计算产品在不同费率卡覆盖期内,对应不同订单时长(如1-30天)的日均价格或总价,将这些预计算值作为字段写入Lucene索引:
- 索引阶段:对每个产品+费率卡组合,遍历费率卡有效期内的每一天,按星期附加费计算当日价格,再统计不同订单时长下的日均/总价,生成
daily_avg_price_7d(7天日均价)、total_price_3d(3天总价)等字段。同时保留费率卡的startdate、enddate、priority字段用于日期匹配。 - 查询阶段:先通过
RangeQuery筛选出覆盖订单起止日期的费率卡,再根据订单时长匹配对应的预计算价格字段,过滤出价格在目标范围内的产品,最后按该预计算字段排序。 - 注意:若订单周期超出预计算范围,需补充动态计算逻辑;同时要确保同一日期范围内取最高优先级费率卡的预计算价格。
方案二:用FunctionQuery动态计算订单周期价格
通过Lucene的自定义FunctionQuery,在查询时实时计算订单期间的实际价格,无需预计算,灵活性更高:
- 索引阶段:将费率卡的所有字段(
startdate、enddate、priority、基础price、各星期附加费)分别用对应类型的字段索引(日期用DatePointField,数值用DoublePointField)。 - 查询阶段:
- 先用
RangeQuery筛选出与订单起止日期有重叠的费率卡,再按priority排序取最高优先级的费率卡。 - 自定义
ValueSource实现价格计算逻辑:遍历订单的每一天,根据星期几匹配对应的附加费,累加基础价得到当日价格,再计算整个订单周期的日均价或总价。 - 用
FunctionQuery将计算结果作为价格范围筛选的依据,同时将该ValueSource作为排序字段,实现按实际价格排序。
- 先用
- 注意:动态计算会增加查询耗时,可优化点包括缓存日期与星期的映射关系、简化遍历逻辑等。
方案三:拆分费率卡为日粒度文档索引
将每个费率卡按有效期拆分为单天粒度的文档,每个文档对应产品某一天的实际价格:
- 索引阶段:对每个费率卡的
startdate到enddate的每一天,生成一个独立文档,包含product_id、date、actual_price(基础价+当日星期附加费)、priority字段。 - 查询阶段:
- 用
RangeQuery筛选出订单起止日期内的所有日粒度文档,按product_id分组,每组内取priority最高的文档集合。 - 计算每组文档的日均价格,过滤出日均价在目标范围内的产品,最后按日均价排序。
- 用
- 优点:查询时计算逻辑简单;缺点是索引数据量会大幅增加(如年卡会生成365个文档),需根据业务规模权衡存储与性能。
方案四:用Lucene Join功能关联产品与费率卡
如果产品与费率卡是一对多关系,可采用父-子文档结构结合Join查询:
- 索引阶段:产品作为父文档(存储产品基础信息),费率卡作为子文档(存储所有费率卡字段,通过
product_id关联父文档)。 - 查询阶段:
- 在子文档中筛选覆盖订单日期的费率卡,按
priority排序取最高优先级的记录。 - 通过Lucene的Join查询关联到对应的父产品文档,计算该费率卡下订单周期的实际价格。
- 过滤价格符合范围的产品,按计算出的价格排序。
- 在子文档中筛选覆盖订单日期的费率卡,按
- 优点:清晰区分产品与费率卡的关联关系,适合多费率卡的复杂场景;需注意优化Join查询的性能,如合理设置缓存。
通用注意事项
- 优先级处理:无论采用哪种方案,都要确保同一日期范围内仅取最高优先级费率卡的价格进行计算,避免多费率卡冲突。
- 价格逻辑对齐:明确业务需求是按订单总价还是日均价筛选排序,确保计算逻辑与业务规则一致。
内容的提问来源于stack exchange,提问作者user2799564
相关产品推荐
相关产品推荐

