Как я могу получить список уникальных терминов из определенного поля в Lucene? - PullRequest
9 голосов
/ 18 января 2012

У меня есть индекс из большого корпуса с несколькими полями. Только одно из этих полей содержит текст. Мне нужно извлечь уникальные слова из всего индекса на основе этого поля. Кто-нибудь знает, как я могу сделать это с Lucene в Java?

Ответы [ 4 ]

27 голосов
/ 17 декабря 2012

Если вы используете API Lucene 4.0, вам нужно вытащить поля из читателя индекса. Затем Fields предлагает способ получить термины для каждого поля в индексе. Вот пример того, как это сделать:

        Fields fields = MultiFields.getFields(indexReader);
        Terms terms = fields.terms("field");
        TermsEnum iterator = terms.iterator(null);
        BytesRef byteRef = null;
        while((byteRef = iterator.next()) != null) {
            String term = new String(byteRef.bytes, byteRef.offset, byteRef.length);

        }

В конце концов, для новой версии Lucene вы можете получить строку из вызова BytesRef:

       byteRef.utf8ToString();

вместо

       new String(byteRef.bytes, byteRef.offset, byteRef.length);

Если вы хотите получить частоту документа, вы можете сделать:

       int docFreq = iterator.docFreq();
9 голосов
/ 18 января 2012

Вы ищете векторов термина (набор всех слов, которые были в поле, и количество раз, которое использовалось каждое слово, исключая стоп-слова).Вы будете использовать IndexReader getTermFreqVector (docid, field) для каждого документа в индексе и заполнять их HashSet.

Альтернативой может быть использование term () и выбор только терминов для интересующей вас области:

IndexReader reader = IndexReader.open(index);
TermEnum terms = reader.terms();
Set<String> uniqueTerms = new HashSet<String>();
while (terms.next()) {
        final Term term = terms.term();
        if (term.field().equals("field_name")) {
                uniqueTerms.add(term.text());
        }
}

Это не оптимальное решение,вы читаете, а затем отбрасываете все остальные поля.В Lucene 4 есть класс Fields, который возвращает term (field) только для одного поля.

3 голосов
/ 26 апреля 2013

Тот же самый результат, только немного чище, заключается в использовании LuceneDictionary в пакете lucene-suggest.Он заботится о поле, которое не содержит никаких терминов, возвращая BytesRefIterator.EMPTY.Это сэкономит вам NPE:)

    LuceneDictionary ld = new LuceneDictionary( indexReader, "field" );
    BytesRefIterator iterator = ld.getWordsIterator();
    BytesRef byteRef = null;
    while ( ( byteRef = iterator.next() ) != null )
    {
        String term = byteRef.utf8ToString();
    }
0 голосов
/ 14 декабря 2017

Ответы с использованием TermsEnum и terms.next() имеют незначительное отклонение от одной ошибки.Это потому, что TermsEnum уже указывает на первый член, поэтому while(terms.next()) приведет к пропуску первого члена.

Вместо этого используйте цикл for:

TermEnum terms = reader.terms();
for(Term term = terms.term(); term != null; terms.next(), term = terms.term()) {
    // do something with the term
}

Для изменениякод из принятого ответа:

IndexReader reader = IndexReader.open(index);
TermEnum terms = reader.terms();
Set<String> uniqueTerms = new HashSet<String>();
for(Term term = terms.term(); term != null; terms.next(), term = terms.term()) {
        if (term.field().equals("field_name")) {
                uniqueTerms.add(term.text());
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...