MultiFieldQueryParser和通配符

时间:2015-01-21 19:50:09

标签: lucene lucene.net

我正在尝试设置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;
    }

现在返回零点击。

1 个答案:

答案 0 :(得分:1)

如果您只是想要所有条款,无论它们出现的顺序或接近程度如何,这都是一个简单的修复。只需添加:

parser.setDefaultOperator(QueryParser.Operator.AND);

如果您的所有查询都将从您希望匹配的字段的开头开始,那么您可以将字段更改为未分析。如果没有分析,那么简单的通配符查询就可以完成这项工作。但是,如果您希望能够查询以下内容,这将不是一个好的解决方案:"HUNG SOOTHING HERBAL"


或者,SpanQueries来救援。这在Java中肯定更好,因为在v3.1中我们使用了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