Ошибка обновления индекса eXist-db версии 2 до 4.5 - PullRequest
0 голосов
/ 19 декабря 2018

Я занимаюсь обновлением и тестированием большой установки и обнаружил одну проблему, которую не могу понять.У меня есть большая коллекция документов, в которой мой индекс создается следующим образом:

<collection xmlns="http://exist-db.org/collection-config/1.0">
    <index xmlns:mods="http://www.loc.gov/mods/v3" xmlns:xlink="http://www.w3.org/1999/xlink">
        <fulltext default="none" attributes="false"/>
        <lucene>
            <analyzer class="org.apache.lucene.analysis.standard.StandardAnalyzer">
                <param name="stopwords" type="org.apache.lucene.analysis.util.CharArraySet"/>
            </analyzer>
            <analyzer id="ws" class="org.apache.lucene.analysis.WhitespaceAnalyzer"/>
            <text qname="p"/>
            <text qname="li"/>
            <text qname="h1"/>
            <text qname="h2"/>
            <text qname="h3"/>
        </lucene>
    </index>
</collection>

В моей версии 2 это прекрасно работает.Запрос возвращает только элемент в списке (p, li, h1, h2, h3).Также only возвращает те элементы с текстом в элементе (как и ожидалось).Функция поиска:

declare function ls:ls($collection as xs:string, $phrase as xs:string) as element()* {
    for $hit in collection(xmldb:encode-uri($collection))//*[ft:query(.,
        <query>
            <phrase>{$phrase}</phrase>
        </query>
        )]
        order by $hit/ancestor::div[@class='content']/@doc/string()
        return 
            <tr>
                <td>
                    {$hit/ancestor::div[@class='content']/@doc/string()}
                </td>
                <td>
                    {$hit/ancestor::div[@class='content']/@title/string()}
                </td>
                <td>
                    {local-name($hit)}
                </td>
                <td class="hit_text">
                    {normalize-space($hit)}
                </td>
            </tr>
};

Чтобы увидеть результат, вот снимок результатов веб-страницы:

enter image description here

Конечно, это не все результаты, но, поверьте мне ... это только возврат именованных элементов и только тех, в которых есть «сердце».

После экспорта / импорта контента в новую версию4 установка почти все остальное работает отлично.Однако даже после переиндексации содержимого тот же самый xQuery возвращает нежелательные элементы более высокого уровня (например, div), а также элементы, которые не содержат поисковую фразу.

Например, этот же запрос показывает такой же результат:

enter image description here

Теперь, как ни странно, если я изменю функцию, чтобы удалить подстановочный знак и идти только после "h1" (или любого другого из названных элементов), это работает:

for $hit in collection(xmldb:encode-uri($collection))//h1[ft:query(.,

Выход:

enter image description here

Вы можете видеть, что в отличие от предыдущего примера, h1 без "сердца""не возвращается.

Что я пропустил в своем обновлении?есть ли какие-то изменения в Lucene, которые я пропустил или не понимаю?

Обновление

Как хак (ИМХО), это работает:

let $targets := collection(xmldb:encode-uri($collection))//*[local-name(.) = 'p' or local-name(.) = 'h1' or local-name(.) = 'h2' or local-name(.) = 'h3' or local-name(.) = 'li']
    for $hit in $targets[ft:query(.,
        <query>
            <phrase>{$phrase}</phrase>
        </query>
        )]

Но если я удаляю созданиенабор узлов $ target и помещает collection () в «for», тогда он не работает.

Update II

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

Так что же я упустил в обновлении?У меня есть conf.xml с призывом к Lucene в обоих случаях.Любые намеки на то, что искать, было бы замечательно.

Обновление III

Может быть, это в журналах проблема?Я сомневаюсь, что поиск в журнале версии 2.x показывает ту же ошибку.

2018-12-19 19:27:05,570 [qtp14962548-143] ERROR (AnalyzerConfig.java [configureAnalyzer]:173) - Lucene index: analyzer class org.apache.lucene.analysis.WhitespaceAnalyzer not found. (org.apache.lucene.analysis.WhitespaceAnalyzer) 
2018-12-19 19:27:38,852 [qtp14962548-43] INFO  (NativeBroker.java [reindexCollection]:1844) - Start indexing collection /db/EIDO/data/Core 
2018-12-19 19:27:54,837 [qtp14962548-43] INFO  (NativeBroker.java [reindexCollection]:1854) - Finished indexing collection /db/EIDO/data/Core in 15985 ms. 

Обновление IV

Я изменил файл collection.xconf, как предложено, для удаления стоп-слов и удаленияWhitespaceAnalyzer:

<collection xmlns="http://exist-db.org/collection-config/1.0">
    <index xmlns:mods="http://www.loc.gov/mods/v3" xmlns:xlink="http://www.w3.org/1999/xlink">
        <fulltext default="none" attributes="false"/>
        <lucene>
            <analyzer class="org.apache.lucene.analysis.standard.StandardAnalyzer"/>
            <text qname="p"/>
            <text qname="li"/>
            <text qname="h1"/>
            <text qname="h2"/>
            <text qname="h3"/>
        </lucene>
    </index>
</collection>

Я переиндексировал коллекцию.Из журнала:

2018-12-20 02:14:56,803 [qtp31631875-34] INFO  (NativeBroker.java [reindexCollection]:1844) - Start indexing collection /db/EIDO/data/Core 
2018-12-20 02:15:16,553 [qtp31631875-34] INFO  (NativeBroker.java [reindexCollection]:1854) - Finished indexing collection /db/EIDO/data/Core in 19750 ms. 

Я получаю точно такой же результат.

Обновление V

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

Обновление VI

Я не люблю толкаться!Теперь, глядя на результаты, по сути, этот поиск в текущей установке:

 for $hit in collection(xmldb:encode-uri($collection))//*[ft:query(.,
        <query>
            <phrase>{$phrase}</phrase>
        </query>
        )]

Возвращает каждый элемент в базе данных, независимо от того, содержит он $ фразу или нет.Возвращает div, потом child p, потом, возможно, span span.Все они.Неважно, существует ли слово на самом деле в тексте.

Если я заменим подстановочный знак «*» на «h1», он возвращает только те h1, которые на самом деле содержат этот текст.Значит что-то не так или сломано или?Я, конечно, могу изменить список элементов, передаваемых в запрос ft: точным элементам (p, h1, h2, h3, li), но этот запрос будет длиться вечно через 4,5, а несколько секунд за 2.

Вероятно, последнее обновление

Я сдался и переустановил все, включая Monex.Я реэкспортировал существующую БД и импортировал ее.Я только изменяю порт на 80, хотя есть и другие изменения, которые я обычно делаю.

Теперь, даже пытаясь запустить панель мониторинга (после импорта), выдает:

javax.servlet.ServletException: javax.servlet.ServletException: An error occurred while processing request to /exist/apps/dashboard/: err:XPST0081 error found while loading module restxq: Error while loading module modules/restxq.xql: Invalid qname text:groups
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
    at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:724)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.Server.handle(Server.java:531)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:352)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:760)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:678)

Что указывает мне на то, чтоэкспорт базы данных, а затем повторный импорт никогда не будут работать, если у вас установлены другие приложения.

К сожалению, мне приходится разбираться и искать альтернативные решения.Я мог попытаться просто восстановить данные или что-то в этом роде, но в приложении было 10 000 пользователей.Это не может быть воссоздано.

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

И просто заметьте ... после установки свежей, чистой базы данных и без изменений я могу получить доступ к Monex или панели инструментов.Если я импортирую из своей резервной копии (как требуется, потому что она не совместима с двоичным кодом), все это ломается.

Это очевидная проблема для разработчиков.

Обновление снова

Я сделал полностью чистую установку.После этого я могу получить доступ к Monex без проблем.Затем я восстановил свою базу данных.ПРИМЕЧАНИЕ. В момент его завершения возникает вопрос о том, хочу ли я обновить приложения.Не уверен, что правильный ответ, может быть, это одна проблема, и я отвечаю неправильно (я отвечаю нет).

После того, как все будет переустановлено, я смогу нормально добраться до БД и всего моего приложения.Но при попытке запустить Monex теперь я получаю:

<exception>
    <path>/db/apps/monex/modules/view.xql</path>
    <message>err:XPST0081 error found while loading module indexes: Error while loading module indexes.xqm: Invalid qname text:index-terms</message> 
</exception>

Правильный ли ответ да для обновления приложений?Я предполагаю, что это означает, что Monex, который я установил только с чистой установкой, перезаписывается моей резервной копией версии 2, и это вызывает ошибку.

Я взломал часть индекса monex, вызывающую проблему, и получил Monexбежать.Итак, он использует Lucene:

enter image description here

Итак, одно наблюдение заключается в том, почему Monex работает нормально, но восстановление моей (старой) БД убивает его.Это не должно быть AFAIK.

возможно, кто-то может объяснить этот результат мне, я не понимаю второй пункт, но я подозреваю, что это тот, который возвращает все:

enter image description here

ОК, работает

Итак.Во-первых, я понял, что восстановление моего / db разрушит все / apps (например, monex) в новой установке.Кажется странным для меня или плохое планирование моего или других.Таким образом, чтобы решить эту проблему, у меня есть новая резервная копия установки.

После установки новой версии eXist я восстанавливаю свою старую базу данных, а затем сразу же возобновляю новую установку заново.Это переписывает все / apps (например, monex) с последними версиями, которые были установлены из моей резервной копии, но не разрушает мою.Извините, смешно.

Теперь после этого я смог проверить и увидеть, используется ли индекс Lucene.Но это все, что он сказал мне, ничего больше (как я подозревал).

Очевидно, что в интеграции Lucene изменилось поведение.В моей старой версии я отправлял каждый элемент, и он возвращал только хиты.В этой новой версии вы не можете сделать это.Если вы отправите что-то похожее, что сделано в приведенном выше коде, оно все равно вернет его как «хит», даже если его нет.Таким образом, $ collection // * отправляет всю структуру в запрос и возвращает все, независимо от того, есть попадание или нет.Раньше он так себя не вел.

Таким образом, решение (которое я так ненавижу даже говорить) - вы можете отправлять только элементы запроса, который вы хотите найти, чтобы увидеть, есть лиэто контент, который является хитом.ВОТ ЭТО ДА.Опять извините, но если я ошибаюсь, пожалуйста, покажите мне, но это полный взлом.Если я создаю индекс всех p, я ожидаю, что p вернется, только если я выполню общий поиск, отправив его p, h1 и т. Д. Что происходит сейчас, это отправляет все обратно, ударил или нет, если вы не попросите точно то же самоеимя элемента, который вы проиндексировали.

Это похоже на поздний / ранний переплет.В старом eXist я отправлял $ coll / [ft: query ... и он возвращал то, что было у меня в качестве идентифицированных элементов в моем индексе.Теперь это не работает таким образом, поэтому вы не можете выполнить цикл for для $ coll / [ft: query ..., поскольку он по-прежнему возвращает everything .ИМХО, что это неправильно.

Итак, чтобы решить, я сделал это, в основном сначала выполнил поиск, а затем перебрал результаты.

declare function ls:ls($collection as xs:string, $phrase as xs:string) as element()* {
    let $coll := collection(xmldb:encode-uri($collection))
    let $hits := ($coll//p | $coll//li | $coll//h1 | $coll//h2 | $coll//h3)[ft:query(.,
        <query>
            <phrase>{$phrase}</phrase>
        </query>
        )]
    for $hit in $hits
        order by $hit/ancestor::div[@class='content']/@doc/string()
        return 
            <tr>
                <td>
                    {$hit/ancestor::div[@class='content']/@doc/string()}
                </td>
                <td>
                    {$hit/ancestor::div[@class='content']/@title/string()}
                </td>
                <td>
                    {local-name($hit)}
                </td>
                <td class="hit_text">
                    {normalize-space($hit)}
                </td>
            </tr>
}

;

А теперь яобновлен для тестирования, и это также работает:

let $hits := (collection(xmldb:encode-uri($collection))//*)[ft:query(.,
    <query>
        <phrase>{$phrase}</phrase>
    </query>
    )]
for $hit in $hits ...

Так что теперь это так близко к тому, что у меня было раньше, мне НЕ нужно переходить к явным элементам, что правильно.Проблема в том, что теперь они не могут быть в цикле for.

Ключ здесь:

(collection(xmldb:encode-uri($collection))//*)

против:

collection(xmldb:encode-uri($collection))//*

И так ... всеэтого ... и решение заключается в том, что цикл for должен быть:

for $hit in (collection(xmldb:encode-uri($collection))//*)[ft:query(.,
    <query>
        <phrase>{$phrase}</phrase>
    </query>
    )]

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

Если быть точным, у меня открыты обе системы для тестирования.

Версия 2x:

for $hit in collection(xmldb:encode-uri($collection))//*[ft:query(.,

Одна секунда, правильный ответ.

for $hit in (collection(xmldb:encode-uri($collection))//*)[ft:query(.,

17 секунд, правильный ответ.

Версия 4.5:

for $hit in collection(xmldb:encode-uri($collection))//*[ft:query(.,

10 секунд, совершенно неправильный ответ (возвращены div и non-hit)

for $hit in (collection(xmldb:encode-uri($collection))//*)[ft:query(.,

одна секунда, правильный ответ.

Мне кажетсячто в старом eXist запрос ничего не возвращал, и в этом новом eXist, похоже, он возвращает результат для каждого отправленного элемента, а если индекс не существует, он все равно возвращает его.

Последнее обновлениеte

Просматривая чистую установку conf.xml, я нашел комментарий в записи xquery для enable-query-rewriting.Этот комментарий предполагает, что он является экспериментальным, и установка «да» может привести к неверным результатам.

Я хотел бы заметить, что я не думаю, что коснулся этого, и установка по умолчанию имеет значение «Да».Я сохранил файл conf.xml из чистой установки, так как я в нем многое изменяю (конечно), глядя на чистую установку, я вижу это:

<xquery enable-java-binding="no" disable-deprecated-functions="no" 
        enable-query-rewriting="yes" backwardCompatible="no" 
        enforce-index-use="always"
        raise-error-on-failed-retrieval="no">

Я изменил на «Нет» и перезапустил существующий-db.Теперь все работает, как и раньше, у меня теперь нет проблем с поиском, и он возвращает именно то, что я ожидаю, с запросом, написанным точно так же, как в версии 2x.

Итак ... что я думаю, я узнал

Я реализовал новые индексы диапазонов и переиндексировал коллекцию, основываясь на комментариях ниже, и снова включил переписывание запросов.Проверяя monex, я вижу индексы, но в моих запросах они не используются, он сообщает, что индекс - это устаревший «диапазон», а оптимизация - «нет индекса».

Я обнаружил, что не могу этого сделать (подстановочный знак будетделаю, я предполагаю):

($ collection // foo | $ collection // bar) [содержит (., $ фразу)]

или это

($ collection// foo, $ collection // bar) [содержит (., $ фразу)]

или это

$ testnodes: = $ collection // foo |$ collection // bar

затем

$ testnodes [содержит (., $ фразу)]

Хотя он работает, он не использует индекс нового диапазона.Они всегда сообщают, что индекс не используется.

Но для этого используются полностью оптимизированные индексы нового диапазона:

$ collection // foo [содержит (., $ Фразу)] |$ Коллекции // бар [содержит (., $ Фразы)]

Ответы [ 3 ]

0 голосов
/ 20 декабря 2018

Хотя я все еще новичок в eXist, мне кажется, что две идеи объединяются.

Указание Lucene индексировать что-либо - это не то же самое, что указывать предикат в запросе Xpath.qname для индекса Lucene не означает (я считаю), что данный элемент не будет объектом запроса.Вопрос только в том, что индексирует Lucene для ускорения поиска?Тот факт, что вы обнаружили улучшение скорости с помощью предиката, говорит о том, что это действительно так.

Когда я выполняю поиск, я по-прежнему ограничиваю элементы, подлежащие запросу, независимо от того, что я говорю Lucene для индексации.Лично я не вижу в этом взлома - просто сокращаю «пул поиска».Я не использую local-name() в качестве предиката.Скорее я бы использовал сам элемент.Я не уверен, стоит ли использовать local-name() по сравнению с этим:

let $coll := collection(xmldb:encode-uri($collection))

let target := $coll//p | $coll//h1 | $coll//h2 | $coll//h3 | $coll//li

В зависимости от вашей иерархии XML, вы можете добиться еще большей скорости, сократив пул узлов с помощью collection(xmldb:encode-uri($collection))//some-element

Выше можно использовать, а затем использовать индексы Lucene более эффективно?Это стоит проверить.

Кроме того, хотя я не знаю, какова иерархия вашего XML, вы также можете явно указать Lucene игнорировать определенные элементы (но обычно это для этих элементоввложенные в те, которые вы индексируете):

 <ignore qname="div"/>

Примечание: я использую eXist 4.4

Добавлено: попробуйте использовать index index в дополнение к Lucene.Также я не вижу пространства имен в qnames (плюс у вас работают два пространства имен, и я добавил третье для xmlns:xs в индексе диапазона).

В этом примере предполагается, что (скопировал из документации eXist, указанной выше) пространство имен mods для демонстрации.Но он должен быть добавлен к каждому qname, если в коллекциях xml есть определенное пространство имен.

<collection xmlns="http://exist-db.org/collection-config/1.0">
  <index xmlns:mods="http://www.loc.gov/mods/v3" 
        xmlns:xlink="http://www.w3.org/1999/xlink"  
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <fulltext default="none" attributes="false"/>
    <range>
       <create qname="mods:p" type="xs:string"/>
       <create qname="mods:li" type="xs:string"/>
       <create qname="mods:h1" type="xs:string"/>
       <create qname="mods:h2" type="xs:string"/>
       <create qname="mods:h3" type="xs:string"/>
    </range>
    <lucene>
        <analyzer class="org.apache.lucene.analysis.standard.StandardAnalyzer"/>
        <text qname="mods:p"/>
        <text qname="mods:li"/>
        <text qname="mods:h1"/>
        <text qname="mods:h2"/>
        <text qname="mods:h3"/>
        <ignore qname="mods:div"/>
    </lucene>
  </index>
</collection>

Удаление объявлений пространства имен, которые не используются.

0 голосов
/ 22 декабря 2018

eXist-db 2.2 был выпущен в 2014 году, поэтому при переходе на более поздние версии для двух основных версий наблюдается тенденция не идти вперед.

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

Этот индекс помечен как устаревший с новым индексом диапазона, который будет использоваться вместо него.

Если вы не можете предоставить MWE, вам необходимо выяснить, какие из ваших запросов вызывают старый диапазониндексировать и изменить их на новый или полностью отключить индекс старого диапазона.

Я бы не рекомендовал использовать, например, и старый monex в новом существующем, и произносить yes при запросе на обновление приложений по умолчанию.до новой версии.Вы все еще можете запустить производственный сайт без каких-либо приложений по умолчанию.

Невозможно определить из ваших примеров, как for $hit in (collection(xmldb:encode-uri($collection))//*)[ft:query(., побочные вызовы индекса старого диапазона в вашем приложении, однако он должен дать вам подсказку.Я предполагаю, что если вы избавитесь от этих вызовов, вы увидите, что for $hit in collection(xmldb:encode-uri($collection))//*[ft:query(., будет действовать и действовать одинаково.

0 голосов
/ 20 декабря 2018

Сначала следует устранить ошибки ...

  1. Класс для анализатора пробелов должен быть org.apache.lucene.analysis.core.WhitespaceAnalyzer.

Хотя это не похоже навы ссылаетесь на анализатор пробелов по его 'id', так что вы можете просто удалить его.

Конфигурация для вашего использования StandardAnalyzer выглядит неправильно для меня.Вы указали параметр stopwords, но:
  1. его класс неверен, он должен быть org.apache.lucene.analysis.util. CharArraySet, и
  2. вы не указали ему никаких значений.

Если вы просто хотите использовать стоп-слова по умолчанию, вы можете полностью пропустить этот параметр.

После того, как вы внесли эти изменения, вы должны попробовать переиндексировать и снова просмотреть журналы..

После этого вы должны использовать приложение Monex из Dashboard в eXist 4.5.0 для проверки доступных индексов, чтобы убедиться, что ваши данные проиндексированы, как вы ожидали.

Обновление 1

Из комментария @ kevin-brown:

Из того, что я вижу сегодня, если я это сделаю ($ collection // foo | $ collection // bar) [fn: contains (., 'string')] никакой индекс не используется.Но если я сделаю это $ collection // foo [fn: Содержит (., 'Строка')] |$ collection // bar [fn: содержит (., 'строка')], используется индекс нового диапазона и оптимизация заполнена.

Я могу подтвердить, что в определенной формулировке XQuery,eXist-db неправильно оптимизирует запрос, чтобы использовать индекс диапазона.Это, безусловно, ошибка!

Клиент администратора Java eXist-db позволяет вам показать след запроса:

  1. ($collection//foo | $collection//bar)[fn:contains(., $string)], о котором Кевин сообщил, что не сделалиспользовать индекс, создает трассировку:

    $collection/descendant::{}foo union
        $collection/descendant::{}bar
            [contains(self::node(), $string)]
    
  2. $collection//foo[fn:contains(., $string)] | $collection//bar[fn:contains(., $string)], о которой Кевин сообщил, что он правильно использовал индекс, создает трассировку:

    $collection
    (# exist:optimize-field #)
    (# exist:optimize #) {
        descendant::{}foo[range:contains(self::node(), $string)]
    }
    union $collection
    (# exist:optimize-field #)
    (# exist:optimize #) {
        descendant::{}bar[range:contains(self::node(), $string)]
    }
    

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

Для сравнения, в (1) мы видим, что eXist не удалось правильно определить доступные индексы, которые могут позволить оптимизацию.

К сожалению, также кажется, что eXist-db мог использовать для них неправильную ось, то есть потомок, а не «потомок или сам».

Я открыл проблему GitHub для eXist-db, которая сообщает об этой проблеме.- https://github.com/eXist-db/exist/issues/2363

...