我正在尝试使用apache lucene开发一个日志查询系统。我已经开发了一个演示代码来索引两个文件,然后搜索查询字符串。
第一个文件包含数据 麦克莱恩
第二个文件包含数据 斑
Bellow是我用于编制索引的代码
fis = new FileInputStream(file);
DataInputStream in = new DataInputStream(fis);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
Document doc = new Document();
Document doc = new Document();
doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(fis, "UTF-8"))));
doc.add(new StoredField("filename", file.getCanonicalPath()));
if (indexWriter.getConfig().getOpenMode() == OpenMode.CREATE) {
System.out.println("adding " + file);
indexWriter.addDocument(doc);
} else {
System.out.println("updating " + file);
indexWriter.updateDocument(new Term("path", file.getPath()), doc);
}
如果我使用此代码,那么我会获得proffer结果。但是在显示中我只能显示文件名,因为我只存储了文件名。
所以我修改了代码并使用此代码
存储了文件内容 FileInputStream fis = null;
if (file.isHidden() || file.isDirectory() || !file.canRead() || !file.exists()) {
return;
}
if (suffix!=null && !file.getName().endsWith(suffix)) {
return;
}
System.out.println("Indexing file " + file.getCanonicalPath());
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException fnfe) {
System.out.println("File Not Found"+fnfe);
}
DataInputStream in = new DataInputStream(fis);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
String Data="";
while ((strLine = br.readLine()) != null)
{
Data=Data+strLine;
}
Document doc = new Document();
doc.add(new TextField("contents", Data, Field.Store.YES));
doc.add(new StoredField("filename", file.getCanonicalPath()));
if (indexWriter.getConfig().getOpenMode() == OpenMode.CREATE) {
System.out.println("adding " + file);
indexWriter.addDocument(doc);
} else {
System.out.println("updating " + file);
indexWriter.updateDocument(new Term("path", file.getPath()), doc);
}
根据我的理解,我应该将结果的数量设为1.并且它应该显示包含maclean的文件的文件名和内容
但我得到的结果是
-----------------------结果----------------------- ---
总共0个匹配文件 找到0我在代码中做了什么错误或对此有合理的解释?为什么第一个代码有效,第二个代码不起作用?
搜索查询代码
try
{
Directory directory = FSDirectory.open(indexDir);
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_41);
QueryParser parser = new QueryParser(Version.LUCENE_41, "contents", analyzer);
Query query = parser.parse(queryStr);
System.out.println("Searching for: " + query.toString("contents"));
TopDocs results = searcher.search(query, maxHits);
ScoreDoc[] hits = results.scoreDocs;
int numTotalHits = results.totalHits;
System.out.println("\n\n\n-----------------------Results--------------------------\n\n\n");
System.out.println(numTotalHits + " total matching documents");
for (int i = 0; i < numTotalHits; i++) {
int docId = hits[i].doc;
Document d = searcher.doc(docId);
System.out.println(i+":File name is: "+d.get("filename"));
System.out.println(i+":File content is: "+d.get("contents"));
}
System.out.println("Found " + numTotalHits);
}
catch(Exception e)
{
System.out.println("Exception Was caused in SimpleSearcher");
e.printStackTrace();
}
答案 0 :(得分:1)
我认为您确切的问题是,当您为索引字段创建BufferedReader时,您已经读取了整个文件,并且该流位于文件的末尾,没有进一步阅读。您应该可以通过调用fis.reset();
但是,你不应该这样做。不要将相同的数据存储在两个单独的字段中,一个用于索引,另一个用于存储。而是将相同的字段设置为存储和索引数据。 TextField has a ctor,允许您存储数据和索引,如:
doc.add(new TextField("contents", Data, Field.Store.YES));
答案 1 :(得分:1)
使用StoredField而不是TextField
doc.add(new StoredField(“Data”,Line));
当您使用文本字段时,字符串会被标记化,因此您将无法搜索相同的字符串。存储字段存储整个字符串而不对其进行标记。
答案 2 :(得分:0)
我认为您的代码可能存在两个问题。
首先,我注意到您没有使用近实时搜索,也没有在阅读之前提交作者。 Lucene的IndexReader获取索引的快照,即使用NRT时的提交版本,或者使用NRT时的提交和未提交版本。这可能是您的IndexReader无法看到更改的原因。由于您似乎需要同时阅读和写作,我建议您使用NRT搜索(IndexReader reader = DirectoryReader.open(indexWriter);
)
第二个问题可能是,正如@femtoRgon所说,您存储的数据可能不是您所期望的。我注意到,当您附加文件内容进行存储时,您似乎丢失了EOL字符。我建议您使用Luke检查索引http://www.getopt.org/luke/
答案 3 :(得分:0)
这适用于Lucene 4.5:doc.add(new TextField(“Data”,Data,Field.Store.YES));