Lucene.net 范围查询 +突出显示

发布于 2024-12-07 22:58:25 字数 4683 浏览 5 评论 0原文

Lucene.net 的另一个极端新手提出的问题。

这次,我在使用包含范围的查询和使用突出显示时发现了一个有趣的问题。

我是凭记忆写的,所以请原谅任何语法错误。

我有一个假设的 Lucene 索引:

---------------------------------------------------------
|       date         |               text               |
---------------------------------------------------------
|     1317809124     |       a crazy block of text      |
---------------------------------------------------------
|     1317809284     |       programmers are crazy      |
---------------------------------------------------------

** date is a unix timestamp        

... 并且它们已通过以下方式添加到索引中:

Lucene.Net.Documents.Document doc = new Lucene.Net.Documents.Document();
doc.Add(new Lucene.Net.Documents.Field("text", "some block of text", Lucene.Net.Documents.Field.Store.YES, Lucene.Net.Documents.Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
doc.Add(new Lucene.Net.Documents.Field("date", "some unix timestamp", Lucene.Net.Documents.Field.Store.YES, Lucene.Net.Documents.Field.Index.NOT_ANALYZED));

这就是我查询 Lucene 的方式:

Lucene.Net.Analysis.Standard.StandardAnalyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
Lucene.Net.Search.IndexSearcher searcher = new Lucene.Net.Search.IndexSearcher(Lucene.Net.Store.FSDirectory.Open(_headlinesDirectory), true);
Lucene.Net.QueryParsers.QueryParser parser = new Lucene.Net.QueryParsers.QueryParser(Lucene.Net.Util.Version.LUCENE_29, "text", analyzer);
Lucene.Net.Search.Query query = parser.Parse(queryPhrase);
Lucene.Net.Search.Hits hits = searcher.Search(query);

// code highlighting
Lucene.Net.Highlight.Formatter formatter = new Lucene.Net.Highlight.SimpleHTMLFormatter("<span style=\"background:yellow;\">","</span>");
Lucene.Net.Highlight.SimpleFragmenter fragmenter = new Lucene.Net.Highlight.SimpleFragmenter(50);
Lucene.Net.Highlight.QueryScorer scorer = new Lucene.Net.Highlight.QueryScorer(query);
Lucene.Net.Highlight.Highlighter highlighter = new Lucene.Net.Highlight.Highlighter(formatter, scorer);
highlighter.SetTextFragmenter(fragmenter);     

for (int i = 0; i < hits.Length(); i++)
{
    Lucene.Net.Documents.Document doc = hits.Doc(i);
    Lucene.Net.Analysis.TokenStream stream = analyzer.TokenStream("", new StringReader(doc.Get("text")));
    string highlightedText = highlighter.GetBestFragments(stream, doc.Get("text"), 1, "...");
    Console.WriteLine("--> " + highlightedText);
}

这是我的查询示例:

crazy AND date:[1286273266 TO 32503680000]

查询时,它会找到以下所有结果“crazy”但不输出任何突出显示的文本。

当日期范围被删除并且您只需查询术语:

crazy

...这次突出显示可以正常工作。

我在实现中是否做错了什么,我是否应该考虑新的实现,或者这是一个可能有解决方法的已知问题。

预先感谢 stackeroverflow'ers :)

-- 编辑 --

我已经实施了 LB 的建议(顺便说一句,太棒了!)。我仍然不知道为什么这会起作用,因为我认为 Lucene 是完全的巫术或编程巫术,但它确实如此,我很高兴:)。

为了完整起见,这里是修改后的代码:

Lucene.Net.Analysis.Standard.StandardAnalyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
Lucene.Net.Search.IndexSearcher searcher = new Lucene.Net.Search.IndexSearcher(Lucene.Net.Store.FSDirectory.Open(_headlinesDirectory), true);
Lucene.Net.QueryParsers.QueryParser parser = new Lucene.Net.QueryParsers.QueryParser(Lucene.Net.Util.Version.LUCENE_29, "text", analyzer);

// new line here
parser.SetMultiTermRewriteMethod(Lucene.Net.Search.MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);

Lucene.Net.Search.Query query = parser.Parse(queryPhrase);

// new line here
Lucene.Net.Search.Query query2 = query.Rewrite(searcher.GetIndexReader());
Lucene.Net.Search.Hits hits = searcher.Search(query);

// code highlighting
Lucene.Net.Highlight.Formatter formatter = new Lucene.Net.Highlight.SimpleHTMLFormatter("<span style=\"background:yellow;\">","</span>");
Lucene.Net.Highlight.SimpleFragmenter fragmenter = new Lucene.Net.Highlight.SimpleFragmenter(50);

// changed to use query2
Lucene.Net.Highlight.QueryScorer scorer = new Lucene.Net.Highlight.QueryScorer(query2);

Lucene.Net.Highlight.Highlighter highlighter = new Lucene.Net.Highlight.Highlighter(formatter, scorer);
highlighter.SetTextFragmenter(fragmenter);

for (int i = 0; i < hits.Length(); i++)
{
    Lucene.Net.Documents.Document doc = hits.Doc(i);
    Lucene.Net.Analysis.TokenStream stream = analyzer.TokenStream("", new StringReader(doc.Get("text")));
    string highlightedText = highlighter.GetBestFragments(stream, doc.Get("text"), 1, "...");
    Console.WriteLine("--> " + highlightedText);
}

如果可以的话,请告诉我我是否准确地实施了这些建议。

Yet another Lucene.net question by an extreme newbie to it.

This time, I have found an interesting issue with using a query that contains a range and using highlighting.

I am writing this from memory, so please forgive any syntax errors.

I have a hypothetical Lucene index of this:

---------------------------------------------------------
|       date         |               text               |
---------------------------------------------------------
|     1317809124     |       a crazy block of text      |
---------------------------------------------------------
|     1317809284     |       programmers are crazy      |
---------------------------------------------------------

** date is a unix timestamp        

... and they have been added to the index via this:

Lucene.Net.Documents.Document doc = new Lucene.Net.Documents.Document();
doc.Add(new Lucene.Net.Documents.Field("text", "some block of text", Lucene.Net.Documents.Field.Store.YES, Lucene.Net.Documents.Field.Index.ANALYZED, Lucene.Net.Documents.Field.TermVector.WITH_POSITIONS_OFFSETS));
doc.Add(new Lucene.Net.Documents.Field("date", "some unix timestamp", Lucene.Net.Documents.Field.Store.YES, Lucene.Net.Documents.Field.Index.NOT_ANALYZED));

This is how I am querying Lucene:

Lucene.Net.Analysis.Standard.StandardAnalyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
Lucene.Net.Search.IndexSearcher searcher = new Lucene.Net.Search.IndexSearcher(Lucene.Net.Store.FSDirectory.Open(_headlinesDirectory), true);
Lucene.Net.QueryParsers.QueryParser parser = new Lucene.Net.QueryParsers.QueryParser(Lucene.Net.Util.Version.LUCENE_29, "text", analyzer);
Lucene.Net.Search.Query query = parser.Parse(queryPhrase);
Lucene.Net.Search.Hits hits = searcher.Search(query);

// code highlighting
Lucene.Net.Highlight.Formatter formatter = new Lucene.Net.Highlight.SimpleHTMLFormatter("<span style=\"background:yellow;\">","</span>");
Lucene.Net.Highlight.SimpleFragmenter fragmenter = new Lucene.Net.Highlight.SimpleFragmenter(50);
Lucene.Net.Highlight.QueryScorer scorer = new Lucene.Net.Highlight.QueryScorer(query);
Lucene.Net.Highlight.Highlighter highlighter = new Lucene.Net.Highlight.Highlighter(formatter, scorer);
highlighter.SetTextFragmenter(fragmenter);     

for (int i = 0; i < hits.Length(); i++)
{
    Lucene.Net.Documents.Document doc = hits.Doc(i);
    Lucene.Net.Analysis.TokenStream stream = analyzer.TokenStream("", new StringReader(doc.Get("text")));
    string highlightedText = highlighter.GetBestFragments(stream, doc.Get("text"), 1, "...");
    Console.WriteLine("--> " + highlightedText);
}

Here is an example of my query:

crazy AND date:[1286273266 TO 32503680000]

When this is queried, it finds all the results for "crazy" but does not output any highlighted text.

When the date range is removed and you simply query the term:

crazy

... this time highlighting works properly.

Is there something I am doing wrong in my implementation, should I be looking at a new implementation, or is this a known issue with potentially a work around.

Thank you in advance stackeroverflow'ers :)

-- EDIT --

I have implemented the suggestions from LB (amazing btw!). I still have no idea why this works as I think Lucene is complete voodoo or programming witchcraft, but it does and I am happy :).

For completeness, here is the modified code:

Lucene.Net.Analysis.Standard.StandardAnalyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
Lucene.Net.Search.IndexSearcher searcher = new Lucene.Net.Search.IndexSearcher(Lucene.Net.Store.FSDirectory.Open(_headlinesDirectory), true);
Lucene.Net.QueryParsers.QueryParser parser = new Lucene.Net.QueryParsers.QueryParser(Lucene.Net.Util.Version.LUCENE_29, "text", analyzer);

// new line here
parser.SetMultiTermRewriteMethod(Lucene.Net.Search.MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);

Lucene.Net.Search.Query query = parser.Parse(queryPhrase);

// new line here
Lucene.Net.Search.Query query2 = query.Rewrite(searcher.GetIndexReader());
Lucene.Net.Search.Hits hits = searcher.Search(query);

// code highlighting
Lucene.Net.Highlight.Formatter formatter = new Lucene.Net.Highlight.SimpleHTMLFormatter("<span style=\"background:yellow;\">","</span>");
Lucene.Net.Highlight.SimpleFragmenter fragmenter = new Lucene.Net.Highlight.SimpleFragmenter(50);

// changed to use query2
Lucene.Net.Highlight.QueryScorer scorer = new Lucene.Net.Highlight.QueryScorer(query2);

Lucene.Net.Highlight.Highlighter highlighter = new Lucene.Net.Highlight.Highlighter(formatter, scorer);
highlighter.SetTextFragmenter(fragmenter);

for (int i = 0; i < hits.Length(); i++)
{
    Lucene.Net.Documents.Document doc = hits.Doc(i);
    Lucene.Net.Analysis.TokenStream stream = analyzer.TokenStream("", new StringReader(doc.Get("text")));
    string highlightedText = highlighter.GetBestFragments(stream, doc.Get("text"), 1, "...");
    Console.WriteLine("--> " + highlightedText);
}

If you could, let me know if I have implemented the suggestions accurately.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岁月染过的梦 2024-12-14 22:58:25

首先调用 QueryParser 的

SetMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE)

方法,然后创建一个新查询,

Query newQuery = query.Rewrite(indexReader);

现在您可以使用“newQuery”进行搜索。

First invoke QueryParser's

SetMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE)

method, then create a new query as

Query newQuery = query.Rewrite(indexReader);

Now you can use "newQuery" to make your searches.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文