MultiFieldQueryParser 和通配符

MultiFieldQueryParser and wildcards

我正在尝试设置 lucene.net 3 以便能够在两个字段中搜索一个词组,但遇到问题。这是我想要查询 return:

我希望查询 return 精确短语匹配,例如:

短语:"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" 和其他可能与该短语或该短语的任何其他不完整变体匹配的其他人。

我最初的解决方案是创建一个布尔查询,其中包含短语查询和解析每个单词并使用通配符的查询。

但是这个 return 匹配以及太多不接近适用的结果。 (它会 return "HERBAL TEA" 因为 "HERBAL" 是解析的术语之一......)由于解析的 OR 查询。

这与我拥有的原始 post 有关: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;
    }

这现在 return 零命中。

如果您只想要求所有条款,而不管它们出现的顺序或接近程度,这是一个简单的解决方法。只需添加:

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