Рекомендации по поиску в архиве тысяч документов (pdf и / или xml)

пересмотр зашедшего в тупик проекта и поиск рекомендаций по модернизации тысяч "старых" документов и предоставлению их через интернет.

документы существуют в различных форматах, некоторые устарели: (.док!--4-->, верстальщиков, hardcopy (OCR), PDF, etc.). Средства доступны для переноса документов в "современный" формат, и многие из жестких копий уже были OCR'D в PDF-файлы-мы изначально предполагали, что PDF будет окончательным форматом но мы открыты для предложений (XML?).

Как только все документы будут в общем формате, мы хотели бы сделать их содержимое доступным и поиск через веб-интерфейс. Мы хотели бы, чтобы гибкость возвращала только части (страницы?) всего документа, где найден поиск " хит " (Я считаю, что Lucene / elasticsearch делает это возможным?!?) Может быть, было бы более гибким, если бы содержимое было XML? Если да, то как / где хранить XML? Непосредственно в базе данных или в виде дискретных файлов в файловая система? Как насчет встроенных изображений / графиков в документах?

любопытно, как другие могут подойти к этому. Нет" неправильного " ответа, я просто ищу как можно больше входов,чтобы помочь нам продолжить.

Спасибо за любой совет.

3 ответов


в резюме: я собираюсь рекомендовать ElasticSearch, но давайте разберем проблему и поговорим о том, как реализовать это:

есть несколько частей этого:

  1. извлечение текста из документов, чтобы сделать их режущих
  2. сделать этот текст доступным в качестве полнотекстового поиска
  3. возврат выделенных фрагментов документа
  4. зная, где в формате doc эти фрагменты найдены, чтобы для пейджинг
  5. верните полный doc

что может предоставить ElasticSearch:

  1. ElasticSearch (как Solr) использует Тика для извлечения текста и метаданных из широкого спектра doc формата
  2. это, довольно очевидно, обеспечивает мощный полнотекстовый поиск. Он может быть настроен для анализа каждого документа на соответствующем языке с, stemming, повышение релевантности определенных областей (например, название более важно, чем содержание), ngrams etc. ie стандартный Lucene материал
  3. он может вернуться выделены фрагменты для каждого результата поиска
  4. он не знает, где эти фрагменты происходят в вашем doc
  5. он может хранить оригинальный документ как вложение, или он может хранить и вернуть извлеченный текст. Но это вернет весь документ, а не страницу.

вы можете просто отправить весь документ в ElasticSearch в качестве вложения, и вы получите полнотекстовый поиск. Но точки прилипания (4) и (5) выше: зная, где вы находитесь в doc, и возвращая части doc.

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

сначала часть индексирования: хранение документов в Elasticsearch в:

  1. используйте Tika (или все, что вам удобно), чтобы извлечь текст из каждого документа. Оставьте его как обычный текст или как HTML, чтобы сохранить форматирование. (забудьте о XML, в этом нет необходимости).
  2. также извлеките метаданные для каждого документа: название, авторы, главы, язык, даты и т. д.
  3. сохраните исходный документ в вашей файловой системе и запишите путь, чтобы вы могли обслуживать его позже
  4. в ElasticSearch, индекс" doc " doc которая содержит все метаданные, и, возможно, список глав
  5. индексируйте каждую страницу как документ" страница", который содержит:

    • A родительское поле который содержит идентификатор документа" doc "(см. "отношения родитель-ребенок" ниже)
    • текст
    • номер страницы
    • возможно, название главы или номер
    • любые метаданные, которые вы хотите для поиска

теперь для поиска. Как это сделать, зависит от того, как вы хотите представить свои результаты - по странице или сгруппированы по doc.

результаты по страницам легко. Этот запрос возвращает список совпадающих страниц (каждая страница возвращается полностью) плюс список выделенных фрагментов со страницы:

curl -XGET 'http://127.0.0.1:9200/my_index/page/_search?pretty=1'  -d '
{
   "query" : {
      "text" : {
         "text" : "interesting keywords"
      }
   },
   "highlight" : {
      "fields" : {
         "text" : {}
      }
   }
}
'

отображение результатов, сгруппированных по " doc " с выделениями из текста, немного сложнее. Это невозможно сделать с помощью одного запроса, но немного группировка на стороне клиента приведет вас туда. Одним из подходов может быть:

Шаг 1: Сделайте top-children-query чтобы найти родителя ("doc"), чьи дети ("страница") лучше всего соответствуют запросу:

curl -XGET 'http://127.0.0.1:9200/my_index/doc/_search?pretty=1'  -d '
{
   "query" : {
      "top_children" : {
         "query" : {
            "text" : {
               "text" : "interesting keywords"
            }
         },
         "score" : "sum",
         "type" : "page",
         "factor" : "5"
      }
   }
}

Шаг 2: Соберите идентификаторы " doc "из вышеуказанного запроса и выполните новый запрос, чтобы получить фрагменты из соответствующих" page " docs:

curl -XGET 'http://127.0.0.1:9200/my_index/page/_search?pretty=1'  -d '
{
   "query" : {
      "filtered" : {
         "query" : {
            "text" : {
               "text" : "interesting keywords"
            }
         },
         "filter" : {
            "terms" : {
               "doc_id" : [ 1,2,3],
            }
         }
      }
   },
   "highlight" : {
      "fields" : {
         "text" : {}
      }
   }
}
'

Шаг 3: в вашем приложении сгруппируйте результаты вышеуказанного запроса по doc и отобразите их.

С поиском результаты второго запроса, у вас уже есть полный текст страницы, которую вы можете отобразить. Чтобы перейти на следующую страницу, вы можете просто найти ее:

curl -XGET 'http://127.0.0.1:9200/my_index/page/_search?pretty=1'  -d '
{
   "query" : {
      "constant_score" : {
         "filter" : {
            "and" : [
               {
                  "term" : {
                     "doc_id" : 1
                  }
               },
               {
                  "term" : {
                     "page" : 2
                  }
               }
            ]
         }
      }
   },
   "size" : 1
}
'

или, альтернативно, дайте" page " docs идентификатор, состоящий из $doc_id _ $page_num (например, 123_2), то вы можете просто получить эту страницу:

curl -XGET 'http://127.0.0.1:9200/my_index/page/123_2

детско-родительские отношения:

обычно в ES (и большинстве решений NoSQL) каждый doc/объект независим - реальных отношений нет. От устанавливая отношения " родитель-потомок "между" doc "и" страницей", ElasticSearch гарантирует, что дочерние документы (т. е." страница") хранятся на том же осколке, что и родительский документ ("doc").

это позволяет запускать top-children-query который найдет лучший соответствующий " doc "на основе содержимого"страниц".


Я создал и поддерживаю приложение, которое индексирует и ищет документы 70k+ PDF. Я обнаружил, что необходимо вытащить простой текст из PDF-файлов, сохранить содержимое в SQL и индексировать таблицу SQL с помощью Lucene. В остальном представление было ужасным.


использовать Сургуте или RSolr или подобный, он обрабатывает большинство основных форматов документов. Они используют Solr / Lucene.