C#中的Lucene查询没有找到标点符号

时间:2016-10-20 20:20:28

标签: c# search indexing lucene

我有一个搜索栏,可以对"描述"执行lucene查询。字段,但是当使用撇号时它不会返回结果。例如,我有一个描述为Herter's® EZ-Load 200lb Feeder - 99018的产品。当我搜索" Herter"时,我得到了结果,但如果我搜索" Herter""或" 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");
}

2 个答案:

答案 0 :(得分:1)

这里的问题是分析。您没有指定在这种情况下使用的分析器,所以我假设它是 Object testObject = null; // Change this PowerMock.mockStatic(CACHE.class); expect(CACHE.get(anyString())).andReturn(testObject); PowerMock.replay(CACHE.class);

分析时,“Herter's”一词将被翻译为“herter”。但是,StandardAnalyzer方法中没有应用分析器,所以寻找“herter”有效,但“herter's”却没有。

一种解决方案是使用FindByKeywordQuery,而不是手动构建QueryParser。 QueryParser将处理标记化,小写等。类似的东西:

MultiPhraseQuery

答案 1 :(得分:0)

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

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);
    }
}

希望这有帮助。