Ответ, который зависит только от функций, доступных вам в спецификации XQuery, заставит вас фильтровать результат функции collection()
путем анализа результатов функции base-uri()
на все содержимое коллекции. Например:
for $file in collection('/db/SCTA')[not(contains(replace(base-uri(.), '^.*/([^/]+?)$', '$1'), '_'))]
Как представляется, вы используете существуем, мы можем использовать одну из функций полезности СУЩЕСТВУЕТ, а именно util:document-name()
, чтобы сделать это немного проще:
for $file in collection('/db/SCTA')[not(contains(util:document-name(.), '_'))]
Для документирования функции на util:document-name()
, см. http://exist-db.org/exist/apps/fundocs/view.html?uri=http://exist-db.org/xquery/util#document-name.1.
-
Пока вы не попросите совета о возможностях оптимизации запроса, я вижу некоторые аспекты вашего кода, которые достойны обсуждения.
Если у вас есть причина, кроме того, что здесь показано в примере кода, вы могли бы рассмотреть консолидации ваших двух вложенных выражений FLWOR в одно:
let $param1:= request:get-parameter('param1', 'oyta')
let $docs := collection('/db/SCTA')[not(contains(util:document-name(.), '_'))]
for $p in $docs//tei:p[contains(., $param1)]
let $pid := $p/@xml:id/string()
let $fs := $p/ancestor::tei:div[last()]/@xml:id/string()
let $title := root($p)/tei:TEI/tei:teiHeader/tei:fileDesc/tei:titleStmt/tei:title/string()
order by $fs
return
<p>{$fs}: {$title}: {$pid}: {$p/string()}</p>
Заметьте здесь, что:
- Получим значение
$param1
один раз, а не снова на каждой итерации выражения FLWOR.
- Мы идентифицируем документы в пункте
let
, а не for
, так как мы действительно заинтересованы в итерация последовательности всех элементов tei:p
периода, а не tei:p
элементов внутри каждый документ.
- Мы используем eXist structural index, чтобы спуститься непосредственно к элементам
tei:p
, вместо указания каких-либо промежуточных шагов дочерней оси; мы используем ось предка XPath для достижения максимального значения p
tei:div
; и мы используем функцию root()
, чтобы перейти к узлу документа, чтобы вернуться к tei:teiHeader
(в качестве альтернативы используйте $p/preceding::tei:titleStmt/tei:title
). Для получения дополнительной информации см. Prefer short paths.
- Мы используем предикат, а не пункт
where
. Как указано here in eXist's documentation, предикаты позволяют оптимизатору запросов eXist выжать больше производительности из выражения FLWOR. Нельзя использовать where
; как раз лучше, чтобы прояснить в eXist, по крайней мере.
- Мы используем функцию
string()
вместо data()
и text()
.В некотором смысле это можно рассматривать как стилистический выбор, но после чтения статей, таких как text() is a code smell от Evan Lenz, я предпочитаю точность string()
, когда я хочу получить строковое значение атрибута или одно строковое значение элемента, который может содержать смешанный контент. (Статья в основном охватывает text()
, но увидеть обсуждение data()
в this thread в комментариях.)
Один шаг я не показал здесь применяет полнотекстовый индекс для вашего tei:p
элемента для ускорения и улучшения поиска функции этого запроса. Если вы определили полнотекстовый индекс на tei:p
, вы можете изменить положение for
на:
for $p in $docs//tei:p[ft:query(., $param1)]
И тогда param1
может использовать всю мощь Lucene's query parser syntax, в том числе вытекающих, нечувствительности к регистру (содержит чувствительно к регистру), подстановочные знаки, близость и т. д. Но полное индексирование текста описано в документации eXist: http://exist-db.org/exist/apps/doc/lucene.xml.
это удивительно полезно. Я в основном работаю над этим методом проб и ошибок. Шаги 1-5 будут большим шагом вперед. – Jeff
Это превратило запрос на 3 секунды в запрос 0.17s. С нетерпением ждем встречи :) – Jeff