2015-05-09 3 views
0

Я следующий сбор структуруXQuery исключить некоторые файлы от подчеркивания в имени файла

SCTA 
--lectio1 
    --lectio1.xml 
    --reims_lectio1.xml 
    --sorb_lectio1.xml 
--lectio2 
    --lectio2.xml 
    --reims_lectio2.xml 
    --sorb_lectio2.xml 

Теперь с помощью XQuery, я хочу искать только те файлы, которые не содержат «_».

Следующий запрос работает, но ищет все файлы. Я хочу изменить его так, что он ищет только lectio1.xml и lectio2.xml, а не файлы с «_» 's

for $file in collection('/db/SCTA/') 
    for $p at $i in $file/tei:TEI//tei:p 
     let $param1:= request:get-parameter('param1', 'oyta') 
     let $pid := data($p/@xml:id) 
     let $fs := data($file/tei:TEI/tei:text/tei:body/tei:div/@xml:id) 
     let $title := $file/tei:TEI/tei:teiHeader/tei:fileDesc/tei:titleStmt/tei:title/text() 

     where ($p[contains(., $param1)]) 
     order by $fs 
     return 
     <p>{$fs}: {$title}: {$pid}: {$p/text()}</p> 

Любые идеи?

ответ

3

Ответ, который зависит только от функций, доступных вам в спецификации 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> 

Заметьте здесь, что:

  1. Получим значение $param1 один раз, а не снова на каждой итерации выражения FLWOR.
  2. Мы идентифицируем документы в пункте let, а не for, так как мы действительно заинтересованы в итерация последовательности всех элементов tei:pпериода, а не tei:p элементов внутри каждый документ.
  3. Мы используем eXist structural index, чтобы спуститься непосредственно к элементам tei:p, вместо указания каких-либо промежуточных шагов дочерней оси; мы используем ось предка XPath для достижения максимального значения ptei:div; и мы используем функцию root(), чтобы перейти к узлу документа, чтобы вернуться к tei:teiHeader (в качестве альтернативы используйте $p/preceding::tei:titleStmt/tei:title). Для получения дополнительной информации см. Prefer short paths.
  4. Мы используем предикат, а не пункт where. Как указано here in eXist's documentation, предикаты позволяют оптимизатору запросов eXist выжать больше производительности из выражения FLWOR. Нельзя использовать where; как раз лучше, чтобы прояснить в eXist, по крайней мере.
  5. Мы используем функцию 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.

+0

это удивительно полезно. Я в основном работаю над этим методом проб и ошибок. Шаги 1-5 будут большим шагом вперед. – Jeff

+0

Это превратило запрос на 3 секунды в запрос 0.17s. С нетерпением ждем встречи :) – Jeff

Смежные вопросы