문제
Lucene(특히 Lucene.NET)을 사용하여 이메일 주소 도메인을 검색하고 싶습니다.
예:Gmail 주소로 전송된 모든 이메일을 찾으려면 "@gmail.com"을 검색하고 싶습니다.
"*@gmail.com"에 대해 Lucene 쿼리를 실행하면 오류가 발생하며 쿼리 시작 부분에 별표를 사용할 수 없습니다."foo@gmail.com"은 전체 단어로 표시되고 단어의 일부만 검색할 수 없기 때문에 "@gmail.com"에 대한 쿼리를 실행하면 일치하는 항목이 반환되지 않습니다.
어떻게 해야 하나요?
해결책
누구도 만족스러운 대답을 하지 못했기 때문에 우리는 Lucene 문서를 살펴보기 시작했고 맞춤형 분석기 및 토크나이저를 사용하여 이를 수행할 수 있다는 사실을 발견했습니다.
대답은 다음과 같습니다.WhitespaceAndAtSymbolTokenizer 및 WhitespaceAndAtSymbolAnalyzer를 만든 다음 이 분석기를 사용하여 인덱스를 다시 만듭니다.이렇게 하면 "@gmail.com"을 검색하면 모든 Gmail 주소가 반환됩니다. 방금 만든 Tokenizer 덕분에 해당 주소가 별도의 단어로 표시되기 때문입니다.
소스 코드는 다음과 같습니다. 실제로는 매우 간단합니다.
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);
다른 팁
당신이 해결책을 가지고 있다고 생각합니다만, 제 경우에는 이를 피하고 당신이 인덱싱하는 문서에 email_domain이라는 필드를 추가했을 것입니다. 여기에 이메일 주소의 구문 분석된 도메인을 추가했을 것입니다.어리석게 들릴 수도 있지만 이와 관련된 저장 용량은 매우 적습니다.좀 더 멋지게 만들고 싶다면 일부 도메인에 하위 도메인이 많다고 가정해 보겠습니다. 대신 역방향 도메인이 들어갈 필드를 만들어 com.gmail, com.company.department 또는 ae.eim을 저장하여 찾을 수 있습니다. 'ae'라는 접두사 쿼리가 포함된 모든 아랍에미리트 관련 주소입니다.
또한 있다 setAllowLeading와일드카드
하지만 주의 깊은.이로 인해 성능이 매우 비쌀 수 있습니다(이것이 기본적으로 비활성화되어 있는 이유입니다).어떤 경우에는 이것이 쉬운 해결책이 될 수도 있지만 다음과 같이 사용자 정의 Tokenizer를 선호합니다. 유다 히망고, 도.
반전된 이메일 주소를 색인화하는 별도의 필드를 만들 수 있습니다.'moc.liamg@f'로 'moc.liamg@*”에 대한 쿼리를 할 수있는'moc.liamg@foof '로'foo@gmail.com '을 index.