2014-01-18 2 views
0

SQL 서버의 인덱스에서 소리 나는 해시를 올바르게 생성하는 것으로 보이는 간단한 사용자 정의 분석기가 있습니다. 내 맞춤 분석기로 생성 된 색인을 조회하려는 대부분의 시도는 결과를 반환하지 않습니다. 나는 비슷한 사건을 찾을 수 없었기 때문에 분명히 뭔가 잘못하고있는 것이 틀림 없다.사용자 정의 분석기/필터로 검색 결과가 없습니다.

사용자 정의 필터 :

internal class SoundexFilter : TokenFilter 
{ 
    private readonly ITermAttribute _termAttr; 

    private Queue<Token> soundexTokenQueue 
     = new Queue<Token>(); 

    public SoundexFilter(TokenStream input) 
     : base(input) 
    { 
     _termAttr = AddAttribute<ITermAttribute>(); 
    } 

    public override bool IncrementToken() 
    { 
     if (input.IncrementToken()) 
     { 
      string currentTerm = _termAttr.Term; 
      var hash = Soundex.For(currentTerm); 
      Console.WriteLine("Original: {0}, Hash: {1}", currentTerm, hash); 
      soundexTokenQueue.Enqueue(new Token(hash, 0, hash.Length)); 
      return true; 
     } 
     else if (soundexTokenQueue.Count > 0) 
     { 
      var token = soundexTokenQueue.Dequeue(); 

      _termAttr.SetTermBuffer(token.Term); 
      _termAttr.SetTermLength(token.TermLength()); 
      return true; 
     } 

     return false; 
    } 
} 

사용자 분석기 :

public class SoundexAnalyzer : Analyzer 
{ 
    public override TokenStream TokenStream(string fieldName, TextReader reader) 
    { 
     //create the tokenizer 
     TokenStream result = new StandardTokenizer(Version.LUCENE_30, reader); 

     //add in filters 
     result = new StandardFilter(result); 

     // Add soundex filter 
     result = new SoundexFilter(result); 

     return result; 
    } 
} 

간단한 테스트 프로그램 :

public class Program 
{ 
    private const string NAME = "John Smith"; 
    private const string SEARCH_NAME = "John Smith"; 

    private Analyzer _analyzer = new SoundexAnalyzer(); 
    private Directory _directory = new RAMDirectory(); 

    internal void Run(string[] args) 
    { 
     using (var writer = new IndexWriter(_directory, _analyzer, IndexWriter.MaxFieldLength.UNLIMITED)) 
     { 
      var field = new Field("Name", NAME, Field.Store.YES, Field.Index.ANALYZED); 

      var document = new Document(); 

      document.Add(field); 

      writer.AddDocument(document); 

      // Unnecessary but helps imply intent 
      writer.Commit(); 
     } 

     using (var searcher = new IndexSearcher(_directory)) 
     { 
      var parser = new QueryParser(Version.LUCENE_30, "Name", _analyzer); 
      var query = parser.Parse(SEARCH_NAME); 
      var docs = searcher.Search(query, 10); 

      Console.WriteLine("\nReturned Docs:"); 

      foreach (var scoreDoc in docs.ScoreDocs) 
      { 
       var doc = searcher.Doc(scoreDoc.Doc); 

       Console.WriteLine(doc.Get("Name")); 
      } 
     } 
    } 

    private static void Main(string[] args) 
    { 
     new Program().Run(args); 
    } 
} 

이 코드를 사용하는 것은 성공의 유일한 검색 NAME = "John" 같은 정확히 일치하고 SEARCH_NAME = "John".

이상한 일은 소리 나는 해시가 잘 작동하는 표준 분석기로 루크에서 검색하므로 쓰기가 예상대로 (또는 적어도 내가 예상 한대로) 작동해야합니다.

저는이 문제에 대해 상당한 연구를 수행했으며 도움이 거의 없습니다. 내가 뭘 놓쳤는가?

답변

0

무엇이 문제를 해결했는지 정확히 알지 못했지만 정확히 인 이유는입니다.

기본적으로 질문에 포함 된 내 TokenFilter 구현은 너무 많이 시도하고 있으며 Lucene의 기대치와 일치하지 않는 것으로 보입니다.

음성 해시를 수행하고 ITermAttribute.Term 값을 생성 된 해시로 바꾸기 위해 IncrementToken 구현을 제한함으로써 매우 잘 작동합니다.

TokenFilter 구현 :

public class SoundexFilter : TokenFilter 
{ 
    private readonly ITermAttribute _termAttr; 

    public SoundexFilter(TokenStream input) 
     : base(input) 
    { 
     _termAttr = AddAttribute<ITermAttribute>(); 
    } 

    public override bool IncrementToken() 
    { 
     if (input.IncrementToken()) 
     { 
      string currentTerm = _termAttr.Term; 
      // Any phonetic hash calculation will work here. 
      var hash = Soundex.For(currentTerm); 
      _termAttr.SetTermBuffer(hash); 
      return true; 
     } 

     return false; 
    } 
} 

결과는 모두 인덱스 및 쿼리시에 적용되는 동일한 필터를 필요로하지만, 매우 잘 작동합니다.

부수적으로이 필터의 성능이 내 기대치와 일치하지 않을 수 있으므로 가능한 개선 사항을 식별하기 위해 솔루션을 프로파일 링합니다. 200 만 개가 넘는 문서를 가진 색인에 대해 잠정 응답 시간이 필요하다고 생각한다면이 솔루션을 사용하고자하는 사람들에게도 똑같이 권하고 싶습니다.