• [ lucene FAQ ] NumericField的NumericRangeQuery和QueryParser失效问题


    我们在对数值型字段进行检索时(范围检索、排序等),如果使用传统的文本类型将发生错误!因为文本和数值的比较方式不一样,一个是数值大小,一个是文本先后顺序,这个很容易理解。

    可参见:lucene问题_检索结果怎么排序?对于不同类型(例如int型)的字段排序有什么区别吗?

    当我们索引中有个别字段采用NumericField时,排序没有什么问题。

    例如:

    //索引
    doc.add(new NumericField("f", Store.YES, true).setIntValue(f));
    ...
    //检索,排序
    Sort sort = new Sort(new SortField("f", SortField.INT));
    

    这时,我们想做范围检索,问题就出现了!

    //检索1-20内的数据
    Query q1 = parser.parse("f:[1 TO 20]");
    

    这种方式检索不到数据,但是换下面这种方式就好了!

    //使用NumericRangeQuery
    Query q = NumericRangeQuery.newIntRange("f", 1, 20, true, true);
    

    为什么会出现这种问题?

    比较粗略的说,就是QueryParser并不清楚哪个字段是数值型的,而它统一采用的是String型的比较方式(和字典中的term采用文本比较)。而且数字型字段的term底层存储也不一样,这里没具体研究!

    现在存在这样一个问题:如果统一使用QueryParser进行语法解析,那么针对数值型字段的范围检索需要单独处理,十分不方便,怎么处理?

    有两种方式:

    方式1:

    对QueryParser进行扩展,对数值型字段的范围检索,采用NumericRangeQuery。

    方式2:

    不用数值型字段,就采用传统的字符串,那么怎么保障排序和范围检索不出错呢?

    我们可以首先对数值型字段转成字符串,然后补全N位,不做N位,左补0。

    例如:数值型11,5,41,按照数值排序(升序)就是:5,11,41;

    如果直接转成字符串:"11","5","41",按照字符串排序(升序)就是:"11","41","5";这显然就错了。

    那么如果对字符串进行“补码”(不是二级制的补码),统一补全3位(补全多少位视数值范围而定),那么就转换成:"011","005","041",

    按照字符串排序(升序)就是:"005","011","041",这就解决了排序问题。范围检索类似处理。

    具体参见:http://wiki.apache.org/lucene-java/SearchNumericalFields


    尚未解决的疑惑:

    1.数值型底层存储结构。

    2.排序的具体实现方式。

  • 相关阅读:
    vue-cli快速搭建
    js严格模式下判断数据类型
    js实现本地的图片压缩上传预览
    web端实现图片放大切换显示预览
    swiper.js在隐藏/显示切换时,轮播出现bug的解决办法
    Zepto.js实现fadeIn,fadeOut功能
    ms
    redis 解决秒杀
    单下滑线 事务 锁
    极验
  • 原文地址:https://www.cnblogs.com/huangfox/p/2406385.html
Copyright © 2020-2023  润新知