我正在使用lucene为大量HTML文档创建一个搜索引擎。
我知道我可以使用PostingsHighlight
和朋友来展示片段,用粗体字,类似于谷歌搜索结果,也类似于这个随机的基于Lucene的例子。
然而,与这些例子不同,我需要一个解决方案,即使在用户打开匹配的文档之后,也能保留突出显示的单词,类似于Google Books。
有些单词以
一旦用户打开生成的文档,我希望可以使用lucene获得文档中每个匹配单词的字符偏移量。
我必须将纯文本中的偏移量交叉引用回原始HTML,并编写代码突出显示
<代码>
我怎样才能从露西那里得到我需要的东西?当然,我不必为这“最后一英寸”写我自己的搜索?
好的,我想出了一个可以开始的方法。:)
索引:
StandardAnalyzer analyzer - new StandardAnalyzer()
Directory index = FSDirectory.open(new File("...").toPath());
IndexWriterConfig config = new IndexWriterConfig(analyzer);
addDoc(writer, "...", "...");
addDoc(writer, "...", "...");
addDoc(writer, "...", "...");
// documents need to be read from the data source..
// only add once, or else your docs will be duplicated as you continue to use the system
writer.close();
指定要存储以突出显示的偏移量
private static final FieldType typeOffsets;
static {
typeOffsets = new FieldType(textField.TYPE_STORED);
typeOffsets.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
}
方法addDoc
void addDoc(IndexWriter writer, String title, String body) {
Document doc = new Document();
doc.add(new Field("title", body, typeOffsets));
doc.add(new Field("body", body, typeOffsets));
// you can also add an store a TextField that does not have offsets,
// like a file ID that you wouldn't search on, just need to reference original doc.
writer.addDocument(doc);
}
执行第一次搜索
String q = "...";
String[] fields = new String[] {"title", "body"};
QueryParser parser = new MultiFieldQueryParser(fields, analyzer)
Query query = parser.parse(q)
IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(index));
PostingsHighlighter highlighter = new PostingsHighlighter();
TopDocs topDocs = searcher.search(query, 10, Sort.RELEVANCE);
使用highlighter.highlightFields(字段,查询,搜索器,topDocs)
获取高亮显示的片段。您可以迭代结果。
当您想突出显示最终文档时(即在搜索完成并用户选择结果后),请使用此解决方案(需要进行小编辑)。它通过使用NullFragmenter
将整个内容转换为一个片段。
public static String highlight(String pText, String pQuery) throws Exception
{
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
QueryParser parser = new QueryParser(Version.LUCENE_30, "", analyzer);
Highlighter highlighter = new Highlighter(new QueryScorer(parser.parse(pQuery)));
highlighter.setTextFragmenter(new NullFragmenter());
String text = highlighter.getBestFragment(analyzer, "", pText);
if (text != null)
{
return text;
}
return pText;
}
编辑:您实际上可以在最后一步中使用PostingHighlighter
,而不是Highlighter
,但您必须重写getBreakIterator
,然后重写BreakIterator
,使其认为整个文档是一个句子。
编辑:您可以覆盖getFormatter
来捕获偏移量,而不是试图解析
问题内容: 我想搜索包含许多单词的字符串,并检索与其中任何一个匹配的文档。我的索引方法如下: 这是我的搜索方法。我不想寻找特定的词组,但是其中的任何单词。用于搜索的分析器与用于索引的分析器相同。 我是Lucene的新手。有人可以帮我吗? 问题答案: 使用会精确地尝试将短语“单词列表”与短语坡度0匹配。 如果要匹配单词列表中的 任何 术语,可以使用: 或者,您也可以使用,以便您可以要求查询词的数量的
问题内容: 我们可以像这样在特定document.field中搜索所有单词: 这将搜索词,并在该领域,从而只返回这些文档将在所有这些词场。 但是我想做的却有些不同。 我想进行查找,以便如果该文档字段的所有单词都出现在我的搜索查询中,则它将返回该文档。 例如 假设Elasticsearch数据库中有一个文档 现在,如果我搜索“ a”,它将返回该文档,因为document.title中的所有单词确实存
问题内容: 通过以下查询,我得到的结果包含单词“ International”和“ Shipping”,我还得到了包含“ International”或“ Shipping”的结果。我该怎么做才能确保结果同时包含两个单词而不只是其中之一? 任何帮助将不胜感激,谢谢! 问题答案: 在每个必需的单词前添加一个,然后使用。 11.8.2。 布尔全文搜索 在实现此功能时,MySQL使用了有时称为隐式布尔逻
问题内容: 代码 版画 哪个是对的。 但是从逻辑上讲,子字符串 也匹配正则表达式。 所以,我怎样才能使代码找到那些子也一样,即不仅 多数扩展 之一,也是它的 孩子们 ? 问题答案: 您可以使用诸如和的勉强限定词。与标准相比,它们尽可能少地匹配并且贪婪地匹配,即尽可能地匹配。尽管如此,这仅允许您找到特定的“子匹配项”,而不是全部。使用提前控制非捕获组可以实现更多控制,文档中也有介绍。但是,为了真正找
问题内容: 假设我有以下文档: 我只想在搜索响应中获取所有顶级字段都匹配的嵌套对象。我的意思是,如果我搜索/过滤名称为“ abc”的用户,则需要以下响应 我怎样才能做到这一点? 问题答案: 如果您可以保留除嵌套字段之外的所有根字段,然后在嵌套字段中仅包含匹配的内部匹配,那么我们可以通过指定稍微复杂一些的源过滤参数来重用之前的答案,例如:
问题内容: 是否可以跳过X个第一行,并在一个查询中选择所有其他行?像那样: 它将选择:pqr,stu,vwx,yz 我尝试使用LIMIT和OFFSET完成此操作,但是问题是表是动态的,而且我不知道应该输入哪个LIMIT(我不知道表中有多少行)。 问题答案: 如果只需要最后N行,请尝试以下操作: 这会根据的顺序为您提供最后几条记录。 您可以使用自动递增的主键(希望有一个主键)来确定行的顺序(如果无法