【问题标题】:Lucene query in C# not finding results with punctuationC# 中的 Lucene 查询找不到带有标点符号的结果
【发布时间】:2016-10-20 20:20:28
【问题描述】:

我有一个搜索栏,它在“描述”字段上执行 lucene 查询,但使用撇号时它不会返回结果。例如,我有一个描述为Herter's® EZ-Load 200lb Feeder - 99018 的产品。当我搜索“Herter”时,我得到了结果,但如果我搜索“Herter's”或“Herters”,我没有得到任何结果。这是我的搜索代码:

var query = Request.QueryString["q"];
var search = HttpContext.Current.Server.UrlDecode(query);

var rewardProductLookup = new RewardCatalogDataHelper();
RewardProductSearchCriteria criteria = new RewardProductSearchCriteria()
{
    keywords = search,
    pageSize = 1000,
    sortDirection = "desc"
};

IEnumerable<SkinnyItem> foundProducts = rewardProductLookup.FindByKeywordQuery(criteria);

public IEnumerable<SkinnyItem> FindByKeywordQuery(RewardProductSearchCriteria query)
{
    var luceneIndexDataContext = new LuceneDataContext("rewardproducts", _dbName);
    string fieldToQuery = "rpdescription";
    bool sortDirection = query.sortDirection.ToLower().Equals("desc");

    MultiPhraseQuery multiPhraseQuery = new MultiPhraseQuery();
    var keywords = query.keywords.ToLower().Split(',');
    foreach (var keyword in keywords)
    {
        if (!String.IsNullOrEmpty(keyword))
        {
            var term = new Term(fieldToQuery, keyword);
            multiPhraseQuery.Add(term);
        }
    }

    var booleanQuery = new BooleanQuery();
    booleanQuery.Add(multiPhraseQuery, BooleanClause.Occur.MUST);

    return
        luceneIndexDataContext.BooleanQuerySearch(booleanQuery, fieldToQuery, sortDirection)
            .Where(i => i.Fields["eligibleforpurchase"] == "1");
}

【问题讨论】:

    标签: c# search indexing lucene


    【解决方案1】:

    这里的问题是分析。你没有指定在这种情况下使用的分析器,所以我假设它是StandardAnalyzer

    分析时,术语“Herter's”将被翻译为“herter”。但是,您的 FindByKeywordQuery 方法中没有应用任何分析器,因此寻找“herter”有效,但“herter's”无效。

    一种解决方案是使用QueryParser,而不是手动构造MultiPhraseQuery。 QueryParser 将处理标记化、小写等。比如:

    QueryParser parser = new QueryParser(VERSION, "text", new StandardAnalyzer(VERSION));
    Query query = parser.Parse("\"" + query.keywords + "\"");
    

    【讨论】:

    • 我在 VERSION 中放了什么?
    • 我也不确定如何在我的索引上运行查询。
    • @EricaStockwell-Alpert 您在应用程序中使用的Version enum 的任何成员。可能是 LUCENE_30。就运行它而言,就像您执行任何其他 lucene 查询一样。将其包装在您的布尔查询中,或者直接运行它。
    【解决方案2】:

    单引号是查询中文本字段的分隔符。

    Select * FROM Product where Description = 'foo' 
    

    您需要对查询的任何单引号进行转义或加倍。在循环中试试这个。

    foreach (var keyword in keywords)
    {
        if (!String.IsNullOrEmpty(keyword))
        {
            var term = new Term(fieldToQuery, keyword);
            term = term.Replace("'", "''");
            multiPhraseQuery.Add(term);
        }
    }
    

    你也可以创建一个扩展方法

        [DebuggerStepThrough]
        public static string SanitizeSQL(this string value)
        {
            return value.Replace("'", "''").Replace("\\", "\\\\");
        }
    

    在这种情况下,您可以在循环中执行此操作

    foreach (var keyword in keywords)
    {
        if (!String.IsNullOrEmpty(keyword))
        {
            var term = new Term(fieldToQuery, keyword.SanitizeSQL());
            multiPhraseQuery.Add(term);
        }
    }
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-31
      • 2022-11-20
      • 1970-01-01
      • 2020-01-08
      • 2011-03-22
      • 1970-01-01
      相关资源
      最近更新 更多