Lucene 的 Field 在构造时内容参数可接受一个字符串或者字节数组,流等,不支持 Date 等类型。如果把 Date.toString() 转换成字符串来索引的话那么存储在索引中的样子就不确定(new Date().toString() 为 “Tue Mar 15 13:25:41 GMT+08:00 2011”),也给下次还原来为 Date 类型带来不便。在以前的版本 Lucene 专门提供了 DateField 来索引 Date 类型,但
现在不推荐使用了,而且也无法用,因为 Lucene 的 Document 在 add(Fieldable field) 时接受的是一个 Fieldable 类,然而 DateField 并未实现 Fieldable 接口,保留它是用来读取老的索引文件。
那 Lucene 要怎么索引日期类型呢?说到底,还是把它转换为字符串,搜索的时候从存储的字符串还原出来,辅助工具类是 DateTools, 它所提供的方法:
1 2 3 4 5 6 |
static String dateToString(Date date, DateTools.Resolution resolution); static Date round(Date date, DateTools.Resolution resolution); static long round(long time, DateTools.Resolution resolution); static Date stringToDate(String dateString); static long stringToTime(String dateString); static String timeToString(long time, DateTools.Resolution resolution); |
就是那些把对象转换为字符串,从字符串还原为对象的方法,Resolution 表示解析到哪个程度,有下面的取值:
DateTools.Resolution.DAY,*.HOUR, *.MILLISECOND,*.MINUTE,*.MONTH,*.SECOND,*.YEAR
也就是 DateTools 为我们提供了转换日期为标准格式的方法,你想自己用 SimpleDateFormat 自己来 format() 和 parse() 也是一样的。比如执行以下两行:
String dateStr = DateTools.dateToString(new Date(), DateTools.Resolution.MILLISECOND);
System.out.println(dateStr);
结果是:
20110315052451376
这样的话我们在索引 Date 类型时就这么写了:
1 2 3 4 |
Document doc = new Document(); Date pubdate = new Date(); doc.add(new Field("pubdate", DateTools.dateToString(pubdate,DateTools.Resolution.MILLISECOND), Field.Store.YES, Field.Index.NOT_ANALYZED)); |
搜索到结果之后,再用 DateTools.stringToDate() 返还原 Date 类型即可。
Document targetDoc = indexSearcher.doc(scdoc.doc);
Date pubdate = DateTools.stringToDate(targetDoc.get("pubdate"));
与 DateField 类似的,Lucene 用来索引 Number 类型有 NumericField 类,它是实现了 Fieldable 接口,相反的 NumberTools
是不推荐使用的。
Lucene 不推荐使用的是 DateField 和 NumberTools,应该使用的是 NumericField 和 DateTools,正好交叉了一下。实际上 Lucene 用于索引实现了 Fieldable 接口的类就只有 Field、NumericField 这两个。
索引数字再参考一段代码:
1 2 3 4 5 6 7 8 |
//创建索引 doc.Add(new NumericField("if", Field.Store.YES, true).SetFloatValue(if)); //获取范围 Query q = NumericRangeQuery.NewFloatRange("if", 1, 10, true, true); //排序 mSearcher.Search(q, null, 100, new Sort(new SortField("if", SortField.FLOAT, true))); |
日期也可以用 RangeQuery 作范围查询的。
本文链接 https://yanbin.blog/lucene-index-date-field/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。