我有以下收集结构
SCTA
--lectio1
--lectio1.xml
--reims_lectio1.xml
--sorb_lectio1.xml
--lectio2
--lectio2.xml
--reims_lectio2.xml
--sorb_lectio2.xml
现在使用Xquery,我想只搜索不包含“_”的文件。
以下查询有效,但会搜索所有文件。我想修改它以便它只搜索lectio1.xml和lectio2.xml,而不是搜索带有“_”的文件
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>
有什么想法吗?
答案 0 :(得分:3)
完全依赖于XQuery规范中可用功能的答案,您可以通过解析所有集合内容上collection()
函数的结果来过滤base-uri()
函数的结果。例如:
for $file in collection('/db/SCTA')[not(contains(replace(base-uri(.), '^.*/([^/]+?)$', '$1'), '_'))]
由于您正在使用eXist,我们可以使用eXist的一个实用程序功能,即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
元素的序列 period ,而不是每个文档中的tei:p
元素 。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()
。在某些方面,这可以被视为一种风格选择,但在阅读像Evan Lenz的text() is a code smell这样的文章后,当我想获得属性或单个字符串的值时,我更喜欢string()
的精度可能包含混合内容的元素的字符串值。 (本文主要涵盖text()
,但请参阅评论中对this thread中data()
的讨论。)我在此处未演示的一个步骤是对您的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