1

到目前为止,我发现 Lucene 非常棒,但是我在复制 LIKE 等效搜索时遇到了一些问题。

在我正在处理的应用程序中,我需要“简化”(LIKE)搜索和高级(全文)搜索选项。数据是基于用户的(姓名、位置等),所以不是大量的文本。

在过去,我只是创建一个连接数据库字段名称的 SQL 查询,并用通配符包围这些术语。我可以在我的应用程序中这样做,绕过 lucene 进行简单的用户数据搜索——但使用 lucene 会很好。

我试过正则表达式搜索

var query = QueryParser.Escape(_query);
var search = new RegexQuery(new Term("name",string.Concat(".*", _query, ".*")));

但它们只适用于一列。

我的一个想法是对每个字段进行标记以产生类似于全文搜索的内容,例如:

姓名:保罗

所以我创建了以下名称字段...

保罗·保罗·保罗·奥勒奥

这会破坏在 LIKE SQL 搜索上使用 lucene 的意义吗?它真的会产生我想要的结果吗?

解决此问题的最佳方法是什么?

编辑:

稍微修改一下这个问题的代码:

在单词边界上将字符串拆分为 2 个字符串以最小化长度差异的优雅方法

生成这个标记器:

    private IEnumerable<string> Tokeniser(string _item)
    {
        string s = _item;

        const int maxPrefixLength = 10;
        const int maxSuffixLength = 10;
        const int minStemLength = 1;

        var tokens = new List<string>();


        for (int prefixLength = 0; (prefixLength + minStemLength <= s.Length) && (prefixLength <= maxPrefixLength); prefixLength++)
            for (int suffixLength = 0; (suffixLength + prefixLength + minStemLength <= s.Length) && (suffixLength <= maxSuffixLength); suffixLength++)
            {
                string prefix = s.Substring(0, prefixLength);
                string suffix = s.Substring(s.Length - suffixLength);
                string stem = s.Substring(prefixLength, s.Length - suffixLength - prefixLength);

                if (prefix.Length > 1)
                    if (!tokens.Contains(prefix))
                        tokens.Add(prefix);

                if (suffix.Length > 1)
                    if (!tokens.Contains(suffix))
                        tokens.Add(suffix);

                if (stem.Length > 1)
                    if (!tokens.Contains(stem))
                        tokens.Add(stem);
            }

        return tokens;
    }

搜索结果确实提供了 LIKE 搜索的等价物。我的“用户”表的大小永远只有 9000 个实体——所以至少对我来说,这可能符合我的需要。

这样做有什么缺点吗(除了更大的 lucene 索引?)

4

1 回答 1

1

基于字符的 n-gram(NGramTokenizer、NGramTokenFilter、EdgeNGramTokenizer 和 EdgeNGramTokenFilter 应该提供您需要的功能。

于 2012-07-28T12:29:07.733 回答