我尝试使用Lucene添加搜索功能,但似乎无法获得使用重要空白的索引。我有以下测试用例设置:
RAMDirectory directory = new RAMDirectory();
KeywordAnalyzer analyzer = new KeywordAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
IndexWriter writer = new IndexWriter(directory, config);
Document doc = new Document();
doc.add(new TextField("content", "Bill Evans", Field.Store.NO));
writer.addDocument(doc);
writer.close();
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
QueryParser parser = new QueryParser("content", analyzer);
parser.setSplitOnWhitespace(false);
Query query = parser.parse("Bill E");
TopDocs docs = searcher.search(query, 1);
assertTrue(docs.totalHits > 0);
我使用的是Lucene 6.6.0,根据我的理解KeywordAnalyzer
是我正在寻找的:
"&标记化#34;整个流作为单个令牌。这对于邮政编码,ID和某些产品名称等数据非常有用。
但我似乎无法获得包含空格的任何匹配文档。
关于如何解决这个问题的任何想法?
答案 0 :(得分:1)
当您编制索引时,您只有一个文档,其中包含一个字段且一个字词值为Bill Evans
当您要进行搜索时,TermQuery
生成的QueryParser
会尝试使用字词值Bill E
进行搜索,并且该字词在索引中显然不存在,因此您将获得零命中。
如果用 - Bill Evans
替换搜索字符串,您将获得结果。
首先,您需要分离索引和搜索问题。您只能搜索索引的内容。如果您在没有分成令牌的情况下索引全文而是在搜索时间 - 如果搜索时的输入字符串与索引中的输入字符串不同,则需要生成WildCardQuery
,FuzzyQuery
,PhraseQuery
等。 TermQuery
会搜索确切的字词值。
我的建议是存储全文值(没有令牌 - StringField
会这样做)以及使用类似 - SimpleAnalyzer
之类的内容生成其他令牌。
所以喜欢,
doc.add(new TextField("content", "Bill Evans", Field.Store.NO));
doc.add(new StringField("storedcontent", "Bill Evans", Field.Store.YES));
以上代码SimpleAnalyzer
,您现在将拥有条款 - bill
& evans
(以及作为存储字段的全文)如果您现在使用相同的分析器进行搜索,您的查询就像 - content:bill content:e
&你会得到一个结果。
总而言之 - 系统按照您编码的方式工作:)
首先,要了解您的要求,以及您希望对该索引执行哪种查询。