満足のいく答えが得られなかったので、Lucene のドキュメントを調べてみたところ、カスタム アナライザーとトークナイザーを使用してこれを達成できることがわかりました。
答えは次のとおりです。WhitespaceAndAtSymbolTokenizer と WhitespaceAndAtSymbolAnalyzer を作成し、このアナライザーを使用してインデックスを再作成します。これを行うと、「@gmail.com」を検索すると、すべての gmail アドレスが返されます。これは、先ほど作成したトークナイザーのおかげで別の単語として認識されるためです。
これがソースコードです。実際には非常に単純です。
class WhitespaceAndAtSymbolTokenizer : CharTokenizer
{
public WhitespaceAndAtSymbolTokenizer(TextReader input)
: base(input)
{
}
protected override bool IsTokenChar(char c)
{
// Make whitespace characters and the @ symbol be indicators of new words.
return !(char.IsWhiteSpace(c) || c == '@');
}
}
internal class WhitespaceAndAtSymbolAnalyzer : Analyzer
{
public override TokenStream TokenStream(string fieldName, TextReader reader)
{
return new WhitespaceAndAtSymbolTokenizer(reader);
}
}
それでおしまい!あとは、インデックスを再構築し、この新しいアナライザーを使用してすべての検索を実行するだけです。たとえば、ドキュメントをインデックスに書き込むには:
IndexWriter index = new IndexWriter(indexDirectory, new WhitespaceAndAtSymbolAnalyzer());
index.AddDocument(myDocument);
検索を実行するには、アナライザーも使用する必要があります。
IndexSearcher searcher = new IndexSearcher(indexDirectory);
Query query = new QueryParser("TheFieldNameToSearch", new WhitespaceAndAtSymbolAnalyzer()).Parse("@gmail.com");
Hits hits = query.Search(query);