2011-02-08 6 views
2

ハイフネーションまたは空白で区切られていますが、しばしば1つの単語として使用される単語が多数あります。 例:バスケットボールまたはバスケットボールはバスケットボールとして書くことができます。ハイフネーションされた単語のLucene Indexing/Query strategy

今私指標文のように、言う:"Hey dude, I played basket ball yesterday". は、今私は、[二重引用符なし] "basketball"を照会してみてください。..

この場合、またはその逆のケースでは、(インデックスbasketballとクエリbasket ball)I結果は得られません。直接または間接的にこの問題を解決する方法はありますか?

Edit:
私は例を示して問題を明らかにしました。私の実際のアプリケーションのシナリオでは、IDの索引付けと検索を行います。 インデックスi場合:011 12345、
は私が事前に01112345.

感謝を使用して、それを照会することができるはずです。

+0

あなたのIDと電話番号は、別々のフィールドに保存されているのですか? – ffriend

+0

質問には、あなたの問題にはほとんど関係がない例があります。回答が実際に何をしようとしているかに必ずしも焦点を置くわけではありません。将来的に現実的なシナリオの問題を示す。 – Joel

答えて

0

私はLuceneユーザーではありませんが、ここでは2セントです:インデックスを開始する前に、データを検索したいように前処理しなければなりません。また、誰かがボールを検索した場合、検索結果に表示されますか?もしそうなら、この一文からの入力として2つの文章を作る必要があります( "昨日バスケットボールをしました" & "昨日バスケットボールをしました")。これはあなたが探しているものですか?

3

ハイフンは、ハイフンなどのトークンを分割するStandardTokenizerのようなものを使用していると仮定すると、「バスケットボール」を検索するユーザーは元のテキスト「バスケットボール」(およびその逆)、そこに問題はない。

この問題は、2つの単語と1つの単語の間になります。 「バスケットボール」と「バスケットボール」。 類義語(例:ジャケット/コート、またはあなたの場合はバスケットボール/バスケットボール)を処理する必要があります。

同等の単語のリストを自分で作成するか、またはWordNetのような辞書を使用して、各用語の同義語で索引または検索のいずれかを補うことでこれを克服できます。 SolrにはSynonymFilterがあります(おそらくはhere参照)。

EDIT:

ここで私は、しばらく前に書いた、非常に基本的な同義語フィルタのためのコードです。同義語は外部化されていませんが、簡単に追加できます。

public class SynonymFilter extends TokenFilter { 
    private static final Logger log = Logger.getLogger(SynonymFilter.class); 

    private Stack<Token> synStack = new Stack<Token>(); 

    static CharArrayMap<String[]> synLookup = new CharArrayMap<String[]>(5, true); 
    static { 
     synLookup.put("basketball".toCharArray(), new String[]{"basket ball"}); 
     synLookup.put("trainer".toCharArray(), new String[]{"sneaker"}); 
     synLookup.put("burger".toCharArray(), new String[]{"hamburger"}); 
     synLookup.put("bike".toCharArray(), new String[]{"bicycle", "cycle"}); 
    } 

    // TODO reverse map all the syns to each other e.g. sneaker to trainer 

    protected SynonymFilter(TokenStream input) { 
     super(input); 
    } 

    @Override 
    public Token next(Token reusableToken) throws IOException { 
     if (synStack.size() > 0) 
      return synStack.pop(); 

     Token nextToken = input.next(reusableToken); 
     if (nextToken != null) { 
      addSynonyms(nextToken); 
     } 

     return nextToken; 
    } 

    private void addSynonyms(Token nextToken) { 
     char[] word = Arrays.copyOf(nextToken.termBuffer(), nextToken.termLength()); 
     String[] synonyms = synLookup.get(word); 
     if (synonyms != null) { 
      for (String s : synonyms) { 
       if (!equals(word, s)) { 
        char[] chars = s.toCharArray(); 
        Token synToken = new Token(chars, 0, chars.length, nextToken.startOffset(), nextToken.endOffset()); 
        synToken.setPositionIncrement(0); 
        synStack.add(synToken); 
        log.info("Found synonym: " + s + " for: " + new String(nextToken.term())); 
       } 
      } 
     } 
    } 

public static boolean equals(char[] word, String subString) { 
    return equals(word, word.length, subString); 
} 

public static boolean equals(char[] word, int len, String subString) { 

    if (len != subString.length()) 
     return false; 

    for (int i = 0 ; i < subString.length(); i++) { 
     if (word[len - i - 1] != subString.charAt(subString.length() - i - 1)) 
      return false; 
    } 

    return true; 

} 
} 
+0

@ user326729と@Joel 私の実際のアプリケーションシナリオでは、私は文章を検索していません。私はあるIDを探している。例:電話番号。どのように人々が電話番号を書くのか分からない。 011 12345、01112345、011-12345、011 123 45. – raj

+3

のように、インデックス作成とクエリを実行する前にすべての空白を削除するのはidです。 – Joel

+1

@raj - 解決策はおそらく、アナライザがこれらの電話番号のすべての形式を一般的なものに持っていくことです。たとえば、空白とハイフンを削除した後、数字を連結してできるだけ長い連続番号にします。これはLuceneで実行可能です。 –

関連する問題