到目前为止,我发现 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 索引?)