Пропущенные совпадения при поиске по индексу lucene

#java #indexing #full-text-search #lucene

#java #индексирование #полнотекстовый поиск #lucene

Вопрос:

я индексирую один большой обзор базы данных (только текстовые поля), в котором пользователь должен иметь возможность выполнять поиск (ниже в методе indexFields). Этот поиск ранее выполнялся в базе данных с помощью ILIKE query, но был медленным, поэтому теперь поиск выполняется по индексу. Hovewer, когда я сравниваю результаты поиска по запросу базы данных и результаты, которые я получаю при поиске по индексу, при поиске по индексу всегда получается намного меньше результатов. Я не уверен, допускаю ли я ошибку при индексации или в процессе поиска. Мне кажется, что здесь все имеет смысл. Есть идеи?

Вот код. Все советы приветствуются!

  // INDEXING
StandardAnalyzer analyzer = new StandardAnalyzer(
                Version.LUCENE_CURRENT, stopSet); // stop set is empty
        IndexWriter writer = new IndexWriter(INDEX_DIR, analyzer, true,
                IndexWriter.MaxFieldLength.UNLIMITED);

        indexFields(writer);
        writer.optimize();
        writer.commit();
        writer.close();
        analyzer.close();
  

 private void indexFields(IndexWriter writer) {

    DetachedCriteria criteria = DetachedCriteria
            .forClass(Activit.class);

    int count = 0;
    int max = 50000;
    boolean existMoreToIndex = true;

    List<Activit> result = new ArrayList<Activit>();


    while (existMoreToIndex) {

        try {
            result = activitService.listPaged(count, max);
            if (result.size() < max)
                existMoreToIndex = false;

            if (result.size() == 0)
                return;

            for (Activit ao : result) {
                Document doc = new Document();
                doc.add(new Field("id", String.valueOf(ao.getId()),
                        Field.Store.YES, Field.Index.ANALYZED));
                if(ao.getActivitOwner()!=null)
                    doc.add(new Field("field1", ao.getActivityOwner(),Field.Store.YES, Field.Index.ANALYZED));
                if(ao.getActivitResponsible() != null)
                    doc.add(new Field("field2", ao.getActivityResponsible(), Field.Store.YES,Field.Index.ANALYZED));

                try {
                    writer.addDocument(doc);
                } catch (CorruptIndexException e) {
                    e.printStackTrace();

            }
            count  = max;
  

  //SEARCH
    public List<Activit> searchActivitiesInIndex(String searchCriteria) {
    Set<String> stopSet = new HashSet<String>(); // empty because we do not    want to remove stop words
    Version version = Version.LUCENE_CURRENT;
    String[] fields = {
            "field1", "field2"};
    try {
        File tempFile = new File("C://testindex");
        Directory INDEX_DIR = new SimpleFSDirectory(tempFile);
        Searcher searcher = new IndexSearcher(INDEX_DIR, true);

        QueryParser parser = new MultiFieldQueryParser(version, fields, new StandardAnalyzer(
                version, stopSet));


        Query query = parser.parse(searchCriteria);

        TopDocs topDocs = searcher.search(query, 500);

        ScoreDoc[] hits = topDocs.scoreDocs;


        //here i always get smaller hits lenght

        searcher.close();
    } catch (Exception e) {
        e.printStackTrace();
    }


}
  

Комментарии:

1. Выведите TopDocs.totalHits, если вы этого еще не делаете. Это число даст вам общее количество документов, соответствующих вашему запросу.

2. @Shashikant Kore: я уже делаю это и вижу, что это неверное число, вот почему я опубликовал вопрос.

Ответ №1:

Скорее всего, анализатор делает что-то, чего вы не ожидаете.

Откройте свой индекс с помощью Luke, вы можете увидеть, как выглядят ваши (проанализированные) проиндексированные документы, а также ваши проанализированные запросы — это должно позволить вам увидеть, что происходит не так.

Кроме того, можете ли вы привести пример searchCriteria ? И соответствующий SQL-запрос? Без этого трудно понять, правильно ли выполнена индексация. Вам также может не понадобиться использовать MultiFieldQueryParser , что довольно неэффективно.

Комментарии:

1. Я использую MultiFieldQueryParser (я думаю, вы это пропустили :))! критерии поиска — это просто простые строки, такие как «отель», «горячий» или что-нибудь еще. Я использую MultiFieldQueryParser, потому что я не хочу выполнять поиск по каждому полю отдельно

2. @Julia, это была моя точка зрения, если вы используете MultiFieldQueryParser, вы выполняете поиск по полям отдельно, это просто обеспечивает некоторый синтаксический сахар. Если вы хотите, чтобы ваши ключевые слова совпадали в любом из полей, гораздо лучше объединить текст в одно поле.