Подтвердить что ты не робот

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

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

Документы существуют в разных форматах, некоторые из них устарели: (.doc, PageMaker, hardcopy (OCR), PDF и т.д.). Имеются средства для переноса документов в "современный" формат, и многие из печатных копий уже были OCR'd в PDF файлы - мы предположили, что PDF будет окончательным форматом, но мы открыты для предложений (XML?),

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

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

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

4b9b3361

Ответ 1

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

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

  • Извлечение текста из ваших документов для их индексации
  • Предоставление этого текста в виде полнотекстового поиска
  • Возврат выделенных фрагментов документа
  • Зная, где в документе обнаружены эти фрагменты для подкачки
  • Вернуть полный документ

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

  • ElasticSearch (например, Solr) использует Tika для извлечения текста и метаданных из большого количества документов formats
  • Это, очевидно, обеспечивает мощный полнотекстовый поиск. Он может быть настроен анализировать каждый документ на соответствующем языке с последующим повышением релевантности определенных полей (например, название более важно, чем контент), ngrams и т.д., т.е. стандартный материал Lucene.
  • Он может возвращать выделенные фрагменты для каждого результата поиска
  • Он НЕ знает, где находятся эти фрагменты в вашем документе
  • Он может хранить исходный документ как attachment, или он может хранить и возвращать извлеченный текст. Но он вернет весь документ, а не страницу.

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

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

Сначала указательная часть: сохранение ваших документов в ElasticSearch:

  • Используйте Tika (или все, что вам удобно), чтобы извлечь текст из каждого документа. Оставьте это как обычный текст или как HTML, чтобы сохранить некоторое форматирование. (забудьте о XML, не нужно для этого).
  • Также извлекайте метаданные для каждого документа: название, авторы, главы, язык, даты и т.д.
  • Сохраните исходный документ в своей файловой системе и запишите путь, чтобы впоследствии вы могли его обслуживать.
  • В ElasticSearch индексируйте документ doc, содержащий все метаданные и, возможно, список глав
  • Индексируйте каждую страницу как документ "страницы", который содержит:

    • A родительское поле, которое содержит идентификатор документа 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" из вышеуказанного запроса и выпустите новый запрос, чтобы получить фрагменты из соответствующих документов "страницы":

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
}
'

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

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

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

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

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

Ответ 2

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

Ответ 3

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