我有一个 Lucene.net 索引,其中包含应用多个查询的搜索:
BooleanQuery filterQuery = new BooleanQuery();
if (searchDto.SubCategoryId != Guid.Empty)
{
TermQuery tq = new TermQuery(new Term("SubCategoryId", searchDto.SubCategoryId.ToString()));
filterQuery.Add(tq, Occur.MUST);
}
if (!string.IsNullOrEmpty(searchDto.SearchPhrase))
{
var parser = new MultiFieldQueryParser
(Version.LUCENE_30, new[] { "Title", "Description", "SubCategoryName", "LongDescription" }, analyzer);
var query = parseQuery(searchDto.SearchPhrase, parser);
filterQuery.Add(query, Occur.MUST);
}
topDocs = searcher.Search(filterQuery, null, hits_limit);
这很好用。例如,如果我向它传递子类别 ID,它只会匹配子类别。但是,如何制定一个查询,该查询不是基于我是否向其发送筛选值,而是基于索引记录是否具有其某个字段的值。
例如,其中一个 lucene 索引记录字段是 IsBundle
。现在,如果IsBundle
是true
,如果RelationshipId
与我发送它searchDto.RelationshipId
匹配,我想要记录。如果IsBundle
false
,我不在乎RelationshipId
。所以我的最终结果将是记录的某种组合,其中IsBundle
true
,RelationshipId
与我的searchDto.RelationshipId
匹配,IsBundle
false
折叠逻辑,这不就是相当于
IsBundle==false OR RelationshipID==x
或
var q = new BooleanQuery();
q.Add(new TermQuery(new Term("IsBundle", "true"), Occur.SHOULD);
q.Add(new TermQuery(new Term("RelationshipID", dto.thing), Ocurr.SHOULD);
如果没有关于索引字段 Relationship ID 的细节,我将假设 Relationship ID 是一个字符串类型。
如果指定了 searchDto.Relationship ID,则需要
(RelationshipID:{searchDto.RelationshipID} AND IsBundle:true) OR IsBundle:false
如果未给出 searchDto.Relationship ID
IsBundle:false
此代码将相应的查询添加到 filterQuery。
if (!String.IsNullOrEmpty(searchDto.RelationshipID))
{
BooleanQuery q = new BooleanQuery();
q.Add(new BooleanClause(
new TermQuery(new Term("RelationshipId", searchDto.RelationshipID)), Occur.MUST)
);
q.Add(new BooleanClause(
new TermQuery(new Term("IsBundle", "true")), Occur.MUST)
);
BooleanClause clause = new BooleanClause(q, Occur.SHOULD);
q = new BooleanQuery();
q.Add(clause);
q.Add(new BooleanClause(
new TermQuery(new Term("IsBundle", "false")), Occur.SHOULD)
);
filterQuery.Add(q,Occur.MUST);
}
else
{
filterQuery.Add(new BooleanClause(
new TermQuery(new Term("IsBundle", "false")), Occur.MUST)
);
}
可能有一种优雅的方式来组装查询,但这满足了要求。