2011-02-08 4 views
2

Существует много слов, разделенных пробелами или пробелами, но часто используемых в качестве одного слова. Например: Basket Ball или ball-ball можно написать как баскетбол.Стратегия Lucene Indexing/Query для переносимых слов

Теперь, когда я, как индекс предложения, скажем: "Hey dude, I played basket ball yesterday". Теперь я пытаюсь запросить "basketball" [без двойных кавычек] ..

Этот случай, или в случае, наоборот, I (индекс basketball и запрос basket ball) не получат никаких результатов. Есть ли способ решить эту проблему прямо или косвенно?

Edit:
Я привел пример, чтобы продемонстрировать проблему. В моем фактическом сценарии приложения я буду индексировать и искать идентификаторы. Если я индекс: 011 12345,
я должен быть в состоянии запросить его с помощью 01112345.

Спасибо заранее.

+0

Ваши идентификаторы/телефонные номера хранятся в отдельном поле или они просто встречаются в тексте? – ffriend

+0

нет смысла иллюстрировать ваш вопрос с примером, который не имеет большого отношения к вашей проблеме, так как это означает, что любые ответы не обязательно будут сосредоточены на том, что вы _активно пытаетесь сделать. В будущем продемонстрируйте проблему с реалистичным сценарием. – Joel

ответ

0

Я не пользователь Lucene, но вот мои 2 цента: перед началом индексирования вы должны предварительно обработать свои данные, чтобы они выглядели так, как вы хотите их искать. Вы также хотите, чтобы он появлялся в результатах поиска, если кто-то ищет только мяч? Если да, тогда вы должны сделать два предложения в качестве вклада, сделанных из этого единственного предложения («Эй, чувак, я вчера играл в баскетбол» & «Эй, чувак, я вчера играл в баскетбол») и индексирую их обоих. Это то, что вы ищите?

3

В этом случае проблема не в этом, ведь если вы используете что-то вроде StandardTokenizer, которое разбивается на маркеры, такие как дефисы, тогда пользователи, ищущие «баскетбольный мяч», будут соответствовать оригинальному тексту «Basket-Ball» (и vica-versa), поэтому проблем нет.

Вопрос идет между двумя словами и одним эквивалентом слова, например. «баскетбол» и «баскетбол». Вам в основном нужно обрабатывать синонимы (например, куртка/пальто или в вашем случае баскетбол/баскетбол).

Вы можете преодолеть это, создав список эквивалентных слов самостоятельно или используя словарь, например 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 В моем фактическом сценарии приложения я не ищу предложения. Я ищу какой-то Ид. Например, номер телефона. Вы никогда не знаете, как люди пишут телефонные номера. например 011 12345, 01112345, 011-12345, 011 123 45. – raj

+3

хорошо, если это идентификатор, выделите все пробелы перед индексацией и запросом. – Joel

+1

@raj. Возможно, решение состоит в том, что ваш анализатор доводит все формы этих телефонных номеров до общего, скажем, сначала удаляя пустое пространство и дефисы, а затем объединяет цифры, чтобы добраться до максимально возможного смежного числа. Это можно сделать в Lucene. –

Смежные вопросы