我正在使用StandardAnalyser为10个文本文档建立索引。
public static void indexDoc(final IndexWriter writer, Path filePath, long timstamp)
{
try (InputStream iStream = Files.newInputStream(filePath))
{
Document doc = new Document();
Field pathField = new StringField("path",filePath.toString(),Field.Store.YES);
Field flagField = new TextField("ashish","i am stored",Field.Store.YES);
LongPoint last_modi = new LongPoint("last_modified",timstamp);
Field content = new TextField("content",new BufferedReader(new InputStreamReader(iStream,StandardCharsets.UTF_8)));
doc.add(pathField);
doc.add(last_modi);
doc.add(content);
doc.add(flagField);
if(writer.getConfig().getOpenMode()==OpenMode.CREATE)
{
System.out.println("Adding "+filePath.toString());
writer.addDocument(doc);
}
} catch (IOException e) {
e.printStackTrace();
}
}
上面的是用于索引文档的代码段。 出于测试目的,我正在搜索一个名为“ ashish”的字段。
当我使用QueryParser时,Lucene会按预期提供搜索结果。
public static void main(String[] args) throws Exception
{
String index = "E:\\Lucene\\Index";
String field = "ashish";
int hitsPerPage = 10;
IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(index)));
IndexSearcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new StandardAnalyzer();
QueryParser parser = new QueryParser(field, analyzer);
String line = "i am stored";
Query query = parser.parse(line);
// Query q = new TermQuery(new Term("ashish","i am stored"));
System.out.println("Searching for: " + query.toString());
TopDocs results = searcher.search(query, 5 * hitsPerPage);
ScoreDoc[] hits = results.scoreDocs;
int numTotalHits = Math.toIntExact(results.totalHits);
System.out.println(numTotalHits + " total matching documents");
for(int i=0;i<numTotalHits;i++)
{
Document doc = searcher.doc(hits[i].doc);
String path = doc.get("path");
String content = doc.get("ashish");
System.out.println(path+"\n"+content);
}
}
以上代码演示了如何使用QueryParser检索所需的字段,该字段正常工作。它命中了所有10个文档,因为我正在为所有10个文档存储此字段。这里一切都很好。
但是,当我使用TermQuery API时,却没有得到想要的结果。 我正在介绍我对TermQuery所做的代码更改。
public static void main(String[] args) throws Exception
{
String index = "E:\\Lucene\\Index";
String field = "ashish";
int hitsPerPage = 10;
IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(index)));
IndexSearcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new StandardAnalyzer();
// QueryParser parser = new QueryParser(field, analyzer);
String line = "i am stored";
// Query query = parser.parse(line);
Query q = new TermQuery(new Term("ashish","i am stored"));
System.out.println("Searching for: " + q.toString());
TopDocs results = searcher.search(q, 5 * hitsPerPage);
ScoreDoc[] hits = results.scoreDocs;
int numTotalHits = Math.toIntExact(results.totalHits);
System.out.println(numTotalHits + " total matching documents");
for(int i=0;i<numTotalHits;i++)
{
Document doc = searcher.doc(hits[i].doc);
String path = doc.get("path");
String content = doc.get("ashish");
System.out.println(path+"\n"+content);
System.out.println("----------------------------------------------------------------------------------");
}
}
对stackoverflow本身的示例Lucene TermQuery and QueryParser进行了一些研究,但未找到任何实际的解决方案,而且这些示例中的lucene版本非常老。
不胜感激。
提前谢谢!
答案 0 :(得分:1)
我在这篇文章中得到了我问题的答案 link that explains how TermQuery works
TermQuery直接搜索整个String。当索引数据经常被标记化时,此行为将给您不正确的结果。
在发布的代码中,我正在将整个搜索字符串传递给TermQuery,例如
查询q = new TermQuery(new Term(“ ashish”,“我已存储”));
现在在上述情况下,Lucene会按原样查找“我已存储”,这是永远不会找到的,因为在索引时该字符串已被标记化。
相反,我尝试像 Query q = new TermQuery(new Term(“ ashish”,“ stored”));
以上查询给了我预期的结果。
谢谢, 灰烬
答案 1 :(得分:0)
真正的问题是您的查询字符串在这里没有得到分析。因此,请使用与索引文档时所用的分析器相同的分析器,并尝试使用以下代码分析查询字符串然后进行搜索。
IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(index)));
IndexSearcher searcher = new IndexSearcher(reader);
QueryParser parser = new QueryParser("ashish", analyzer);
Query query = new TermQuery(new Term("ashish", "i am stored"));
query = parser.parse(query.toString());
ScoreDoc[] hits = searcher.search(query, 5).scoreDocs;