これまでのところ、Lucene は素晴らしいと思いますが、LIKE と同等の検索を複製する際にいくつか問題があります。
私が取り組んでいるアプリケーションでは、「簡易」(LIKE) 検索と高度な (全文) 検索のオプションが必要です。データはユーザーベース (名前、場所など) であるため、大量のテキストではありません。
以前は、用語をワイルドカードで囲み、db フィールド名を連結する SQL クエリを作成するだけでした。私のアプリケーションでは、ユーザー データの単純な検索のために lucene をバイパスしてそれを行うことができますが、lucene を使用すると便利です。
正規表現検索を試しました
var query = QueryParser.Escape(_query);
var search = new RegexQuery(new Term("name",string.Concat(".*", _query, ".*")));
ただし、それらは 1 つの列でのみ機能します。
私が持っていたアイデアの 1 つは、各フィールドをトークン化して、全文検索に似たものを生成することでした。
名前: ポール
だから私は次の名前フィールドを作成します...
ポール・パウ・パ・アウル・ウル・アウ
これは、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 エンティティしかないので、少なくとも私にとっては、これが私のニーズに合うかもしれません。
これを行うことの欠点はありますか (はるかに大きなルセン インデックスを除いて?)