我们在对数值型字段进行检索时(范围检索、排序等),如果使用传统的文本类型将发生错误!因为文本和数值的比较方式不一样,一个是数值大小,一个是文本先后顺序,这个很容易理解。
可参见: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.排序的具体实现方式。