2012-01-11 8 views
0

私はLuceneまたは可能であれば重複する可能性のある英語の最初の文字を&の姓で確認することができるいくつかの種類のインデックスを示す例を探しています。重複チェックでは、一般的なニックネーム、つまりロバートのためのボブとウィリアムのためのビルとスペルミスを考慮に入れる必要があります。誰かが例を知っていますか?重複する英語の名前を検出する

ユーザー登録時に重複検索を実行する予定です。新しいユーザーレコードは、ユーザー名を格納するデータベーステーブルから作成されたインデックスに対してチェックする必要があります。

答えて

2

すべての可能な組み合わせ(Bob-> Robert、Robert-> Bob、etc ...)を持つように、インデックス作成中にfirstNameにSynonymFilterを使用します。既存のユーザーのインデックスを作成します。

次に、QueryParser(アナライザでSynonymFilterを使用しない)を使用して、一部のファジークエリを尋ねます。

になり
public class NameDuplicateTests { 
    private Analyzer analyzer; 
    private IndexSearcher searcher; 
    private IndexReader reader; 
    private QueryParser qp; 

    private final static Multimap<String, String> firstNameSynonyms; 
    static { 
     firstNameSynonyms = HashMultimap.create(); 
     List<String> robertSynonyms = ImmutableList.of("Bob", "Bobby", "Robert"); 
     for (String name: robertSynonyms) { 
      firstNameSynonyms.putAll(name, robertSynonyms); 
     } 
     List<String> willSynonyms = ImmutableList.of("William", "Will", "Bill", "Billy"); 
     for (String name: willSynonyms) { 
      firstNameSynonyms.putAll(name, willSynonyms); 
     } 
    } 

    public static Analyzer createAnalyzer() { 
     return new Analyzer() { 
      @Override 
      public TokenStream tokenStream(String fieldName, Reader reader) { 
       TokenStream tokenizer = new WhitespaceTokenizer(reader); 
       if (fieldName.equals("firstName")) { 
        tokenizer = new SynonymFilter(tokenizer, new SynonymEngine() { 
         @Override 
         public String[] getSynonyms(String s) throws IOException { 
          return firstNameSynonyms.get(s).toArray(new String[0]); 
         } 
        }); 
       } 
       return tokenizer; 
      } 
     }; 
    } 


    @Before 
    public void setUp() throws Exception { 
     Directory dir = new RAMDirectory(); 
     analyzer = createAnalyzer(); 

     IndexWriter writer = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.UNLIMITED); 
     ImmutableList<String> firstNames = ImmutableList.of("William", "Robert", "Bobby", "Will", "Anton"); 
     ImmutableList<String> lastNames = ImmutableList.of("Robert", "Williams", "Mayor", "Bob", "FunkyMother"); 

     for (int id = 0; id < firstNames.size(); id++) { 
      Document doc = new Document(); 
      doc.add(new Field("id", String.valueOf(id), Field.Store.YES, Field.Index.NOT_ANALYZED)); 
      doc.add(new Field("firstName", firstNames.get(id), Field.Store.YES, Field.Index.ANALYZED)); 
      doc.add(new Field("lastName", lastNames.get(id), Field.Store.YES, Field.Index.NOT_ANALYZED)); 
      writer.addDocument(doc); 
     } 
     writer.close(); 

     qp = new QueryParser(Version.LUCENE_30, "firstName", new WhitespaceAnalyzer()); 
     searcher = new IndexSearcher(dir); 
     reader = searcher.getIndexReader(); 
    } 

    @After 
    public void tearDown() throws Exception { 
     searcher.close(); 
    } 

    @Test 
    public void testNameFilter() throws Exception { 
     search("+firstName:Bob +lastName:Williams"); 
     search("+firstName:Bob +lastName:Wolliam~"); 
    } 

    private void search(String query) throws ParseException, IOException { 
     Query q = qp.parse(query); 
     System.out.println(q); 
     TopDocs res = searcher.search(q, 3); 
     for (ScoreDoc sd: res.scoreDocs) { 
      Document doc = reader.document(sd.doc); 
      System.out.println("Found " + doc.get("firstName") + " " + doc.get("lastName")); 
     } 
    } 
} 

+firstName:Bob +lastName:Williams 
Found Robert Williams 
+firstName:Bob +lastName:wolliam~0.5 
Found Robert Williams 

希望に役立ちます

これは私が思いついたコードです!

関連する問題