我在Android上使用Lucene 3.6.2。使用的代码和观察结果如下。
索引代码:
public void indexBookContent(Book book, File externalFilesDir) throws Exception {
IndexWriter indexWriter = null;
NIOFSDirectory directory = null;
directory = new NIOFSDirectory(new File(externalFilesDir.getPath() + "/IndexFile", book.getBookId()));
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(LUCENE_36, new StandardAnalyzer(LUCENE_36));
indexWriter = new IndexWriter(directory, indexWriterConfig);
Document document = createFieldsForContent();
String pageContent = Html.fromHtml(decryptedPage).toString();
((Field) document.getFieldable("content")).setValue(pageContent);
((Field) document.getFieldable("content")).setValue(pageContent);
((Field) document.getFieldable("content")).setValue(pageContent.toLowerCase());
}
private Document createFieldsForContent() {
Document document = new Document();
Field contentFieldLower = new Field("content", "", YES, NOT_ANALYZED);
document.add(contentFieldLower);
Field contentField = new Field("content", "", YES, ANALYZED);
document.add(contentField);
Field contentFieldNotAnalysed = new Field("content", "", YES, NOT_ANALYZED);
document.add(contentFieldNotAnalysed);
Field recordIdField = new Field("recordId", "", YES, ANALYZED);
document.add(recordIdField);
return document;
}
public JSONArray searchBook(String bookId, String searchText, File externalFieldsDir, String filter) throws Exception {
List<SearchResultData> searchResults = null;
NIOFSDirectory directory = null;
IndexReader indexReader = null;
IndexSearcher indexSearcher = null;
directory = new NIOFSDirectory(new File(externalFieldsDir.getPath() + "/IndexFile", bookId));
indexReader = IndexReader.open(directory);
indexSearcher = new IndexSearcher(indexReader);
Query finalQuery = constructSearchQuery(searchText, filter);
TopScoreDocCollector collector = TopScoreDocCollector.create(100, false);
indexSearcher.search(finalQuery, collector);
ScoreDoc[] scoreDocs = collector.topDocs().scoreDocs;
}
private Query constructSearchQuery(String searchText, String filter) throws ParseException {
QueryParser contentQueryParser = new QueryParser(LUCENE_36, "content", new StandardAnalyzer(LUCENE_36));
contentQueryParser.setAllowLeadingWildcard(true);
contentQueryParser.setLowercaseExpandedTerms(false);
String wildCardSearchText = "*" + QueryParser.escape(searchText) + "*";
// Query Parser used.
Query contentQuery = contentQueryParser.parse(wildCardSearchText);
return contentQueryParser.parse(wildCardSearchText);
}
我已经完成了这个:&#34; Lucene: Multi-word phrases as search terms&#34;,我的逻辑似乎并不相同。
我怀疑是这些字段被覆盖了。 另外,我需要中文语言支持,除了两个或更多单词支持的问题之外,它还适用于此代码。
答案 0 :(得分:1)
预先注意一点:
看到像这样的搜索实现似乎立刻有点奇怪。通过所有可用字符串进行线性搜索看起来过于复杂。我不知道你到底需要完成什么,但我怀疑你会更好地为你的文本进行适当的分析,而不是在关键词分析文本上做双重通配符,这将会表现不佳,并且不会提供太大的灵活性。搜索。
继续讨论更具体的问题:
您使用不同的分析方法多次分析同一字段中的相同内容。
Field contentFieldLower = new Field("content", "", YES, NOT_ANALYZED);
document.add(contentFieldLower);
Field contentField = new Field("content", "", YES, ANALYZED);
document.add(contentField);
Field contentFieldNotAnalysed = new Field("content", "", YES, NOT_ANALYZED);
document.add(contentFieldNotAnalysed);
相反,如果您确实需要所有这些分析方法可用于搜索,您应该将它们编入不同字段的索引中。一起搜索这些没有意义,所以它们不应该在同一个领域。
然后你有这种模式:
Field contentField = new Field("content", "", YES, ANALYZED);
document.add(contentField);
//Somewhat later
((Field) document.getFieldable("content")).setValue(pageContent);
不要这样做,这没有意义。只需将您的内容传递给构造函数,然后将其添加到您的文档中:
Field contentField = new Field("content", pageContent, YES, ANALYZED);
document.add(contentField);
特别是如果您选择继续在同一字段中以多种方式进行分析,则无法在不同的Field实现中获取一个(getFieldable
将始终返回第一个一个补充)
这个查询:
String wildCardSearchText = "*" + QueryParser.escape(searchText) + "*";
正如您所提到的,使用多个术语不会很好。它与QueryParser语法相悖。你最终得到的是:*two terms*
,它将被搜索为:
field:*two field:terms*
哪个不会针对您的关键字字段生成任何匹配(大概)。 QueryParser根本不适合这种查询。您需要自己构建一个通配符查询:
WildcardQuery query = new WildcardQuery(new Term("field", "*two terms*"));