我应该使用什么方法来索引以下一组文件。
每个文件包含大约 500k 行字符 (400MB) - 字符不是单词,它们是,为了问题起见,可以说是随机字符,没有空格。
我需要能够找到包含给定 12 个字符的字符串的每一行,例如:
行: AXXXXXXXXXXXXJJJJKJIDJUD....最多 200 个字符
有趣的部分:XXXXXXXXXXXX
搜索时,我只对字符 1-13 感兴趣(因此XXXXXXXXXXXX)。搜索后,我希望能够读取包含 XXXXXXXXXXXX 的行,而无需循环遍历文件。
我写了以下poc(简化了问题:
索引:
while ( (line = br.readLine()) != null ) {
doc = new Document();
Field fileNameField = new StringField(FILE_NAME, file.getName(), Field.Store.YES);
doc.add(fileNameField);
Field characterOffset = new IntField(CHARACTER_OFFSET, charsRead, Field.Store.YES);
doc.add(characterOffset);
String id = "";
try {
id = line.substring(1, 13);
doc.add(new TextField(CONTENTS, id, Field.Store.YES));
writer.addDocument(doc);
} catch ( IndexOutOfBoundsException ior ) {
//cut off for sake of question
} finally {
//simplified snipped for sake of question. characterOffset is amount of chars to skip which reading a file (ultimately bytes read)
charsRead += line.length() + 2;
}
}
搜索:
RegexpQuery q = new RegexpQuery(new Term(CONTENTS, id), RegExp.NONE); //cause id can be a regexp concernign 12char string
TopDocs results = searcher.search(q, Integer.MAX_VALUE);
ScoreDoc[] hits = results.scoreDocs;
int numTotalHits = results.totalHits;
Map<String, Set<Integer>> fileToOffsets = new HashMap<String, Set<Integer>>();
for ( int i = 0; i < numTotalHits; i++ ) {
Document doc = searcher.doc(hits[i].doc);
String fileName = doc.get(FILE_NAME);
if ( fileName != null ) {
String foundIds = doc.get(CONTENTS);
Set<Integer> offsets = fileToOffsets.get(fileName);
if ( offsets == null ) {
offsets = new HashSet<Integer>();
fileToOffsets.put(fileName, offsets);
}
String offset = doc.get(CHARACTER_OFFSET);
offsets.add(Integer.parseInt(offset));
}
}
这种方法的问题在于,它将每行创建一个文档。
您能否给我一些提示,告诉我如何使用 lucene 解决这个问题,以及 lucene 是否可以解决这个问题?
最佳答案
不要为每次迭代添加新文档,而是使用相同的文档并不断向其添加具有相同名称的字段,例如:
Document doc = new Document();
Field fileNameField = new StringField(FILE_NAME, file.getName(), Field.Store.YES);
doc.add(fileNameField);
String id;
while ( (line = br.readLine()) != null ) {
id = "";
try {
id = line.substring(1, 13);
doc.add(new TextField(CONTENTS, id, Field.Store.YES));
//What is this (characteroffset) field for?
Field characterOffset = new IntField(CHARACTER_OFFSET, bytesRead, Field.Store.YES);
doc.add(characterOffset);
} catch ( IndexOutOfBoundsException ior ) {
//cut off
} finally {
if ( "".equals(line) ) {
bytesRead += 1;
} else {
bytesRead += line.length() + 2;
}
}
}
writer.addDocument(doc);
这会将每行的 id 添加为同一字段中的新术语。相同的查询应该继续有效。
不过,我不太确定如何使用 CharacterOffset
字段。与 ids 一样,每个值都将作为另一个术语附加到字段的末尾。它不会与特定术语直接相关,除了人们会假设该字段中有相同数量的标记之外。如果您需要检索特定行,而不是整个文件的内容,则当前逐行索引的方法可能是最合理的。
关于java - Lucene 索引 - 很多文档/短语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19043867/