Проблема при обновлении индекса eXist-db версии 2 до 4.5

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

<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). Он также только возвращает те элементы с текстом в элементе (как и ожидалось). Функция поиска:

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

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

введите описание изображения здесь

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

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

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

введите описание изображения здесь

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

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

Урожайность:

введите описание изображения здесь

Вы можете видеть, что в отличие от предыдущего примера, 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>
        )]

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

Обновление II

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

Так что же я упустил при обновлении? У меня есть 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, затем дочерний p, затем, возможно, дочерний диапазон. Все они. Не имеет значения, существует ли слово в тексте на самом деле.

Если я изменю подстановочный знак «*» на «h1», он вернет только те h1, в которых действительно есть этот текст. Так что-то не то или сломано или? Я, конечно, могу изменить список элементов, переданный в ft: query, на конкретные рассматриваемые элементы (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:

введите описание изображения здесь

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

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

введите описание изображения здесь

ОК, работает

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

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

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

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

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

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

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

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, кажется, возвращает результат для каждого отправленного элемента, и если индекса не существует, он все равно возвращает его.

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

Просматривая чистую установку 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">

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

Итак ... то, что, как мне кажется, я узнал

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

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

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

или это

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

или это

$ testnodes: = $ collection // foo | $ collection // бар

тогда

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

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

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

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


person Kevin Brown    schedule 19.12.2018    source источник
comment
Сначала мы должны устранить ошибки.   -  person adamretter    schedule 20.12.2018
comment
Я надеюсь, что @adamretter хотя бы прочитает все это и прокомментирует. Особенно с учетом того, что это явно разное поведение между версиями.   -  person Kevin Brown    schedule 22.12.2018
comment
Я читал, могу ли я набраться терпения, пожалуйста. Это проект с открытым исходным кодом, и мы все стараемся бесплатно вносить то свободное время, которое у нас есть.   -  person adamretter    schedule 22.12.2018
comment
Так что я думаю, что смогу следить за своими проблемами. Для этого нам нужно иметь возможность воспроизвести ваши выводы. Не могли бы вы предоставить абсолютный минимум данных, предположительно, всего один или, может быть, два небольших документа, чтобы мы могли выполнить ваши запросы по ним и увидеть те же результаты, оттуда мы можем обсудить.   -  person adamretter    schedule 22.12.2018
comment
Создать такую ​​базу данных и попытаться ее упростить невозможно. Но если вам нужен доступ как к старой, так и к новой версии, я буду рад предоставить ее в частном порядке.   -  person Kevin Brown    schedule 22.12.2018
comment
Если я правильно понимаю, вы говорите, что ваши вызовы ft: query в eXist-db 4.x не принимают и не возвращают узлы, которые вы ожидали бы в eXist-db 2.x. Хотя это может быть непросто, я не вижу причин, по которым вы не могли бы предоставить нам небольшой модульный тест XQuery и XML, воспроизводящий вашу проблему. Помогите нам помочь вам!   -  person adamretter    schedule 22.12.2018
comment
Я согласен с Адамом. Было бы действительно полезно иметь небольшой набор данных, конфигурацию индекса и небольшой запрос для работы. Имея это общее заземление, мы сможем лучше помочь вам найти решение. Конечно, есть и другие советы, которыми мы можем помочь - научиться восстанавливать только ваше приложение и предотвратить восстановление старых копий стандартных приложений. Но поскольку ваш исходный пост был посвящен вопросу данных и запросов, давайте разберемся с этим.   -  person Joe Wicentowski    schedule 22.12.2018
comment
Я понимаю ваши комментарии и пожелания. К сожалению, база данных, которую я переношу с v2 на v4.5, составляет 900 МБ, и у нее много тысяч пользователей. Я мог бы потратить несколько часов, чтобы попытаться построить простой пример как в старом, так и в новом. Просто у меня сейчас нет времени. У меня также есть много сред с открытым исходным кодом (у меня есть RenderX, а также @cloudformatter и несколько других приложений). Что я мог сделать, так это составить несколько открытых запросов к этой БД (новая и старая - это базы данных DEV для системы PROD) и позволить вам увидеть результаты. Я не могу опубликовать учетные данные для доступа, но отправлю их вам в частном порядке   -  person Kevin Brown    schedule 22.12.2018
comment
@KevinBrown Это может занять у вас несколько часов, но если вы хотите использовать общедоступный форум, такой как StackOverflow, для решения проблемы, тогда потребуется некоторое время, и все это должно быть общедоступным, чтобы другие тоже могли получить выгоду. Я не думаю, что переключение на частные дела полезно. Как и вы, наше время тоже ограничено. Мы не можем тратить время на изучение вашей конкретной системы, запросов или организации удаленного доступа и т. Д. Мы рады помочь вам, но давайте сделаем это открытым и воспроизводимым образом.   -  person adamretter    schedule 22.12.2018
comment
@adamretter, отправьте, пожалуйста, конец вопроса выше. Я считаю, что при чистой установке для параметра enable-query-rewriting установлено значение yes, и это нарушает мой запрос. Я не знаю, что он делал, но если я изменю его на no, все будет работать точно так же, как в версии 2.   -  person Kevin Brown    schedule 22.12.2018
comment
Таким образом, переписчик запросов попытается переписать ваш запрос для достижения различных оптимизаций. Было бы неплохо воспроизвести вашу проблему, чтобы мы могли ее решить. Я рад, что вам удалось найти решение. Если у вас есть время, мы будем признательны, если вы создадите проблему в Git-хабе с достаточной информацией, чтобы мы могли воспроизвести   -  person adamretter    schedule 23.12.2018
comment
Я согласен @adamretter, сейчас выходной. Может быть, я смогу составить для вас хороший набор тестов за это время.   -  person Kevin Brown    schedule 23.12.2018
comment
Это было бы прекрасно. Спасибо   -  person adamretter    schedule 23.12.2018
comment
@KevinBrown, я не уверен, что здесь проблема. Оптимизатор запросов пытается оптимизировать ваши операторы предиката для индекса нового диапазона, который был введен в версии 3.0.0, поскольку ваша версия 2.2. Приложение не имеет индексов нового диапазона, оно вернется к устаревшему индексу старого диапазона, который планируется удалить в версии 5.0.0. Как вы обнаружили, вы можете либо отключить оптимизатор, либо добавить индексы нового диапазона.   -  person duncdrum    schedule 23.12.2018
comment
Я провел больше исследований и прочитал. Из того, что я вижу сегодня, если я сделаю это ($ collection // foo | $ collection // bar) [fn: contains (., 'String')], индекс не будет использоваться. Но если я сделаю эту $ collection // foo [fn: contains (., 'String')] | $ collection // bar [fn: contains (., 'string')], используется индекс нового диапазона и оптимизация завершена.   -  person Kevin Brown    schedule 23.12.2018
comment
@KevinBrown, ты справился! Спасибо, там баг. Я открыл проблему для eXist-db и обновил свой ответ ниже. Спасибо, что придерживались этого :-)   -  person adamretter    schedule 03.01.2019


Ответы (3)


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

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

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

  1. The config for your use of the StandardAnalyzer looks wrong to me. You have specified a stopwords parameter, but:
    1. its class is wrong, it should be org.apache.lucene.analysis.util. CharArraySet, and
    2. вы не придали ему никакой ценности.

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

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

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

Обновление 1

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

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

Я могу подтвердить, что в определенной формулировке 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.

person adamretter    schedule 20.12.2018
comment
Хорошо, я могу это сделать. Но изменился ли класс по сравнению с моей установленной версией 2.x и версией 4.5? Потому что в моей старой версии он работает как шарм без каких-либо проблем. - person Kevin Brown; 20.12.2018
comment
И мне нужно будет установить Monex, поскольку я никогда не добавляю недействительные приложения в экземпляр PROD, поэтому мне нужно будет внести некоторые изменения для этого. - person Kevin Brown; 20.12.2018
comment
Версия, если Lucene, вероятно, обновлялась, поэтому возможно, что имена классов изменились - person adamretter; 20.12.2018
comment
Monex очень ценен, и его стоит добавить. - person jbrehr; 21.12.2018
comment
Пожалуйста, просмотрите все обновления и решения выше и прокомментируйте. Я думаю, что есть проблема, но я открыт для понимания почему. - person Kevin Brown; 22.12.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"/>

NB: я использую eXist 4.4

Добавлено: попробуйте использовать индекс диапазона в дополнение к 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>

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

person jbrehr    schedule 20.12.2018
comment
(1) Пытался игнорировать на ‹div›, все еще возвращал элементы ‹div› и (2) все, что не объясняет, почему поиск по сердцу вернул h1, текст которого - What is cardiac catherterizaion, в котором даже нигде нет слова сердце. - person Kevin Brown; 21.12.2018
comment
Я бы добавил, что структура простая ... это статья- ›div-› div- ›p | ул | h1 | h2 | h3. И у любого из них может быть промежуток внутри, но на данный момент я только пытаюсь получить то, что у меня было раньше. Запрос возвращал только целевые элементы, а не элементы более высокого уровня (которые содержат элементы более низкого уровня), а также не возвращает элементы, в которых термин не существует. Я добился успеха только благодаря явному именованию, и это очень медленно (как будто он вообще не использует индекс) - person Kevin Brown; 21.12.2018
comment
Monex явно сообщит вам, используется индекс или нет. Это шаг к пониманию того, что происходит, а что не происходит с запросом. - person jbrehr; 21.12.2018
comment
Да, я согласен, и я перестрою с установленным Monex, потому что индекс не используется. Хотя я сомневаюсь, что Monex скажет мне, почему не используется индекс. Запрос сердца во всей БД занимает 1,5 секунды в версии 2 и даже при реализации предложенного выше (после исправления coll на $ coll требуется 3 минуты. - person Kevin Brown; 21.12.2018
comment
Я отредактировал свой комментарий с идеей. У вас нет индекса диапазона, и я также не вижу пространства имен mods: ни на каком qname. Мои индексы не работают без namespace:element в qname. Индексы атрибутов не нуждаются в пространстве имен. - person jbrehr; 21.12.2018
comment
Теперь, когда я присмотрелся, я добавил mods:, но я не уверен, что это фактическое пространство имен, которое вы используете в своей коллекции. (mods фактически является примером пространства имен в документации eXist exist-db.org/exist/apps/doc/newrangeindex#D3.17). Xlink - ваше пространство имен? Тем не менее, я думаю, что это может быть проблемой: если ваши элементы находятся в определенном пространстве имен, то это пространство имен должно быть объявлено, а затем добавлено к каждому индексу элемента. Может это xlink или что-то еще. - person jbrehr; 21.12.2018
comment
Увы, но нет. Нет даже пространства имен, и я попытался все это удалить. Опять же, я считаю, что здесь упущено главное. То, что отлично работает в 2x, не работает в 4.5 после экспорта / импорта. Очевидно, поиск Lucene не используется, и я могу проверить это, установив monex и посмотрев. Но это очевидно. Что не очевидно, так это то, что даже если Lucene не используется, ft: query по-прежнему возвращает вещи, даже если поисковый запрос даже не присутствует в тексте. Я ищу сердце, он возвращает h1, текст которого - панель Foo. Совсем не работает. - person Kevin Brown; 21.12.2018
comment
Эти комментарии помогли больше всего, спасибо вам за это. Я не согласен с тем, как он должен себя вести (или, по крайней мере, как он вел себя в прошлом по сравнению с настоящим). IMHO, если я создаю индекс только с p, li, h1 и отправляю ему все виды элементов ... он должен возвращать только p, li и h1 и ничего больше. Именно так это работало в версии 2. Если я должен сказать, где индексировать И где искать (и они должны быть одинаковыми), это неправильно. - person Kevin Brown; 22.12.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(., действует и работает таким же образом.

person duncdrum    schedule 22.12.2018