huangfox

冰冻三尺,非一日之寒!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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

可参见: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.排序的具体实现方式。

 

 

 

 

 

 

posted on 2012-03-19 17:14  huangfox  阅读(2818)  评论(0编辑  收藏  举报