Как индексировать и искать текстовые файлы в Lucene 3.0.2? - PullRequest
10 голосов
/ 03 ноября 2010

Я новичок в Lucene, и у меня возникают некоторые проблемы при создании простого кода для запроса коллекции текстовых файлов .

Я пытался этот пример , нонесовместим с новой версией Lucene.

UDPATE: Это мой новый код , но он все еще не работает.

Ответы [ 3 ]

33 голосов
/ 04 ноября 2010

Lucene - это довольно большая тема с множеством классов и методов, и вы обычно не можете ее использовать, не понимая хотя бы некоторых основных понятий. Если вам нужна быстро доступная услуга, используйте Solr . Если вам нужен полный контроль над Lucene, продолжайте читать. Я расскажу о некоторых основных концепциях и классах Lucene, которые их представляют. (Для получения информации о том, как читать текстовые файлы в памяти, прочитайте, например, эту статью).

Что бы вы ни собирались делать в Lucene - индексирование или поиск - вам нужен анализатор. Цель анализатора состоит в том, чтобы токенизировать (разбить на слова) и поставить (получить базу слова) ваш вводимый текст. Он также выбрасывает наиболее часто встречающиеся слова, такие как «a», «the» и т. Д. Вы можете найти анализаторы для более чем 20 языков или использовать SnowballAnalyzer и передать язык в качестве параметра.
Чтобы создать экземпляр SnowballAnalyzer для английского языка, вам необходимо:

Analyzer analyzer = new SnowballAnalyzer(Version.LUCENE_30, "English");

Если вы собираетесь индексировать тексты на разных языках и хотите автоматически выбирать анализатор, вы можете использовать LanguageIdentifier tika .

Вам нужно где-то хранить свой индекс. Для этого есть две основные возможности: индекс в памяти, который легко попробовать, и дисковый индекс, который является наиболее распространенным.
Используйте любую из следующих 2 строк:

Directory directory = new RAMDirectory();   // RAM index storage
Directory directory = FSDirectory.open(new File("/path/to/index"));  // disk index storage

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

IndexWriter writer = new IndexWriter(directory, analyzer, true, new IndexWriter.MaxFieldLength(25000));

Любой документ (текстовый файл в вашем случае) представляет собой набор полей. Чтобы создать документ, который будет содержать информацию о вашем файле, используйте это:

Document doc = new Document();
String title = nameOfYourFile;
doc.add(new Field("title", title, Field.Store.YES, Field.Index.ANALYZED));  // adding title field
String content = contentsOfYourFile;
doc.add(new Field("content", content, Field.Store.YES, Field.Index.ANALYZED)); // adding content field
writer.addDocument(doc);  // writing new document to the index

Field конструктор принимает имя поля, его текст и как минимум 2 дополнительных параметра. Сначала флаг, который показывает, должен ли Lucene хранить это поле. Если оно равно Field.Store.YES, у вас будет возможность получить весь текст обратно из индекса, в противном случае будет храниться только информация об этом из индекса.
Второй параметр показывает, должен ли Lucene индексировать это поле или нет. Используйте Field.Index.ANALYZED для любого поля, в котором вы собираетесь искать.
Обычно вы используете оба параметра, как показано выше.

Не забудьте закрыть IndexWriter после выполнения задания:

writer.close();

Поиск немного сложен. Вам понадобится несколько классов: Query и QueryParser, чтобы сделать запрос Lucene из строки, IndexSearcher для фактического поиска, TopScoreDocCollector для сохранения результатов (он передается IndexSearcher в качестве параметра) и ScoreDoc перебирать результаты. Следующий фрагмент показывает, как все это состоит:

IndexSearcher searcher = new IndexSearcher(directory);
QueryParser parser = new QueryParser(Version.LUCENE_30, "content", analyzer);
Query query = parser.parse("terms to search");
TopScoreDocCollector collector = TopScoreDocCollector.create(HOW_MANY_RESULTS_TO_COLLECT, true);
searcher.search(query, collector);

ScoreDoc[] hits = collector.topDocs().scoreDocs;
// `i` is just a number of document in Lucene. Note, that this number may change after document deletion 
for (int i = 0; i < hits.length; i++) {
    Document hitDoc = searcher.doc(hits[i].doc);  // getting actual document
    System.out.println("Title: " + hitDoc.get("title"));
    System.out.println("Content: " + hitDoc.get("content"));
    System.out.println();
}

Записать второй аргумент в конструктор QueryParser - это поле по умолчанию, то есть поле, в котором будет производиться поиск, если не указан квалификатор. Например, если ваш запрос «title: term», Lucene будет искать слово «term» в поле «title» всех документов, но если ваш запрос просто «term», если будет искать в поле по умолчанию, в этом случае - «содержание». Для получения дополнительной информации см. Синтаксис запроса Lucene .
QueryParser также принимает анализатор в качестве последнего аргумента. Это должен быть тот же анализатор, который вы использовали для индексирования текста.

Последнее, что вы должны знать, это TopScoreDocCollector.create первый параметр. Это просто число, которое представляет, сколько результатов вы хотите собрать. Например, если оно равно 100, Lucene соберет только первые (по количеству баллов) 100 результатов и отбросит остальные. Это всего лишь процесс оптимизации - вы собираете лучшие результаты, и если вы не удовлетворены им, вы повторяете поиск с большим числом.

Наконец, не забудьте закрыть поисковик и каталог, чтобы не потерять системные ресурсы:

searcher.close();
directory.close();

РЕДАКТИРОВАТЬ: Также см. Демо-класс IndexFiles из Исходники Lucene 3.0 .

3 голосов
/ 04 ноября 2010
package org.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;


import org.apache.lucene.queryParser.*;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;

public class LuceneSimple {

 private static void addDoc(IndexWriter w, String value) throws IOException {
  Document doc = new Document();
  doc.add(new Field("title", value, Field.Store.YES, Field.Index.ANALYZED));
  w.addDocument(doc);
 }



 public static void main(String[] args) throws CorruptIndexException, LockObtainFailedException, IOException, ParseException {

     File dir = new File("F:/tmp/dir");

  StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);

  Directory index = new RAMDirectory();
  //Directory index = FSDirectory.open(new File("lucDirHello") );


  IndexWriter w = new IndexWriter(index, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);

  w.setRAMBufferSizeMB(200);

  System.out.println(index.getClass() + " RamBuff:" + w.getRAMBufferSizeMB() );

  addDoc(w, "Lucene in Action");
     addDoc(w, "Lucene for Dummies");
     addDoc(w, "Managing Gigabytes");
     addDoc(w, "The Art of Computer Science");
     addDoc(w, "Computer Science ! what is that ?");


     Long N = 0l;

     for( File f : dir.listFiles() ){
      BufferedReader br = new BufferedReader( new FileReader(f) );
      String line = null;
      while( ( line = br.readLine() ) != null ){
       if( line.length() < 140 ) continue;      
       addDoc(w, line);
       ++N;
      }
      br.close();
     }

     w.close();

     // 2. query
     String querystr = "Computer";

     Query q = new QueryParser( Version.LUCENE_30, "title", analyzer ).parse(querystr);


     //search
     int hitsPerPage = 10;

     IndexSearcher searcher = new IndexSearcher(index, true);

     TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);

     searcher.search(q, collector);

     ScoreDoc[] hits = collector.topDocs().scoreDocs;

     System.out.println("Found " + hits.length + " hits.");
     for(int i=0;i<hits.length;++i) {
       int docId = hits[i].doc;
       Document d = searcher.doc(docId);
       System.out.println((i + 1) + ". " + d.get("title"));
     }


     searcher.close();

 }

}
1 голос
/ 03 ноября 2010

Я предлагаю вам взглянуть на Solr @ http://lucene.apache.org/solr/, а не работать с Lucene API

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...