索引数字的场景主要有两种:一是把它们当作字符串一样处理,比如“要是搁以前,术士能暴击10000多,有木有!”中的"10000",它和其它的词没什么区别,你可以把它仅仅想成一个字符串;另一种场景则是某个域只索引数字,且可以搜索数字的范围等,比如设计了某个Field存储邮件的大小,现在要搜索大小在3M-10M的邮件。
对于第一种情况,你要做的仅仅是选一个不会对数字进行分词的分析器。这种分析器很多,比如之前我们用过的WhitespaceAnalyzer和StandardAnalyzer。当然WhitespaceAnalyzer分析器可能仅仅对英语之类的语言还有点用处。对于第二种情况,你不需要为这些专门设计用来存储数字的域进行分词,指定成Field.Index.NOT_ANALYZED就可以了。不过你必须清楚的是,Lucene内部处理的仍然只是String类型!即"10"是排在"2"前面的!若是想支持范围搜索,你需要为数字增加前置0, 即需要索引"02",这样"02"便排在"10"前面了!
public class IndexNumberTest extends TestCase{ private Directory directory; protected void setUp() throws Exception { directory = new RAMDirectory(); IndexWriter writer = getWriter(); Document doc = new Document(); doc.add(new Field("indexNumber", "要是搁以前,术士能暴击10000多,有木有!", Field.Store.YES, Field.Index.ANALYZED)); writer.addDocument(doc); writer.close(); } public void testNumber() throws IOException, ParseException { IndexSearcher is = new IndexSearcher(directory); QueryParser parser = new QueryParser(Version.LUCENE_30, "indexNumber", new StandardAnalyzer(Version.LUCENE_30)); Query query = parser.parse("10000"); TopDocs topDocs = is.search(query, 1); assertEquals(1, topDocs.totalHits); } private IndexWriter getWriter() throws IOException { return new IndexWriter(directory, new StandardAnalyzer(Version.LUCENE_30), IndexWriter.MaxFieldLength.UNLIMITED); } }