我正在尝试设置lucene.net 3,以便能够在两个字段中搜索一个短语并且卡住了。以下是我希望返回的查询:
我希望查询返回精确的词组匹配,如:
短语:“CHING WAN HUNG SOOTHING HERBAL BALM”
结果:“CHING WAN HUNG SOOTHING HERBAL BALM”
以及通配符匹配:
短语:“CHING WAN HUNG SOO”或“CHING WAN HUN”结果:“CHING WAN HUNG SOOTHING HERBAL BALM”以及其他可能与此短语或任何其他不完整变体相匹配的内容。
我最初的解决方案是创建一个布尔查询,同时使用一个短语查询和一个解析每个单词的通配符。
但是这会返回匹配以及太多不合适的结果。 (它将返回“HERBAL TEA”,因为“HERBAL”是已解析的术语之一...)由于已解析的OR查询。
这与我所拥有的原始帖子有关:How to set up a query to return phrases and parts of phrases in lucene.net?想知道我是否可以在标准Lucene.net中执行此操作,而无需借助所提到的Java端口。
有人可以给我任何指导吗? 谢谢!
public override List<TT> ExecuteSearch(string searchQuery, string searchField = "")
{
if (string.IsNullOrEmpty(searchQuery.Replace("*", "").Replace("?", ""))) return new List<TT>();
using (var searcher = new IndexSearcher(Directory, false))
{
var hits_limit = 1000;
var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30, new HashSet<string>());
var fields = new[] {"CompositeName", "SubstanceName"};
var parser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30, fields, analyzer);
parser.AllowLeadingWildcard = true;
parser.PhraseSlop = 0;
var query = ParseWholeQueryWc(searchQuery, fields, parser);
searcher.SetDefaultFieldSortScoring(true, true);
var hits = searcher.Search(query, null, hits_limit, Sort.RELEVANCE).ScoreDocs;
var results = MapLuceneToDataList(hits, searcher);
analyzer.Close();
searcher.Dispose();
return results;
}
}
public Query ParseWholeQueryWc(string searchQuery, string[] fields, QueryParser parser)
{
Query query = new PhraseQuery();
Query query2 = new PhraseQuery();
Query mq = new BooleanQuery();
try
{
var bld = ParseTermWithWildcards(searchQuery);
// phrase
query = parser.Parse("\"" + searchQuery.Trim() + "\"");
// or
query2 = parser.Parse(searchQuery + "*");
// main
((BooleanQuery)mq).Add(query, Occur.SHOULD);
((BooleanQuery)mq).Add(query2, Occur.SHOULD);
}
catch (ParseException ex)
{
throw;
}
return mq;
}
更新
public BooleanQuery ParseWholeQueryWc(string searchQuery, string[] fields, QueryParser parser)
{
BooleanQuery mq = new BooleanQuery();
try
{
string[] qrArr = searchQuery.Split(null);
SpanQuery[] compNmQ = new SpanQuery[qrArr.Length];
SpanQuery[] subsNmQ = new SpanQuery[qrArr.Length];
for (var i = 0; i < qrArr.Length; i++)
{
//CompositeName", "SubstanceName
if (i == qrArr.Length - 1)
{
compNmQ[i] = new SpanTermQuery(new Term("CompositeName", qrArr[i] + "*"));
subsNmQ[i] = new SpanTermQuery(new Term("SubstanceName", qrArr[i] + "*"));
}
else
{
compNmQ[i] = new SpanTermQuery(new Term("CompositeName", qrArr[i]));
subsNmQ[i] = new SpanTermQuery(new Term("SubstanceName", qrArr[i]));
}
}
SpanQuery compNameQ = new SpanNearQuery(compNmQ, 0, true);
SpanQuery subsNameQ = new SpanNearQuery(subsNmQ, 0, true);
// main
((BooleanQuery) mq).Add(compNameQ, Occur.SHOULD);
((BooleanQuery)mq).Add(subsNameQ, Occur.SHOULD);
}
catch (ParseException ex)
{
throw new ArgumentException("BaseLuceneStrategy:ParseWholeQueryWc():" + ex.Message);
}
return mq;
}
现在返回零点击。
答案 0 :(得分:1)
如果您只是想要所有条款,无论它们出现的顺序或接近程度如何,这都是一个简单的修复。只需添加:
parser.setDefaultOperator(QueryParser.Operator.AND);
如果您的所有查询都将从您希望匹配的字段的开头开始,那么您可以将字段更改为未分析。如果没有分析,那么简单的通配符查询就可以完成这项工作。但是,如果您希望能够查询以下内容,这将不是一个好的解决方案:"HUNG SOOTHING HERBAL"
SpanMultiTermQueryWrapper
,但在v3.0.3(以及.Net端口)中,你可以使用SpanRegexQuery
:
SpanQuery[] subqueries = new SpanQuery[4];
subqueries[0] = new SpanTermQuery(new Term("field", "CHING"));
subqueries[1] = new SpanTermQuery(new Term("field", "WAN"));
subqueries[2] = new SpanTermQuery(new Term("field", "HUNG"));
subqueries[3] = new SpanRegexQuery(new Term("field", "SOO.*"));
SpanQuery finalQuery = new SpanNearQuery(subqueries, 0, true)
对其他任何字段执行相同操作,并将它们合并到BooleanQuery
。