xquery按文件名中的下划线排除某些文件

时间:2015-05-09 01:21:55

标签: 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,而不是搜索带有“_”的文件

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> 

有什么想法吗?

1 个答案:

答案 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>

请注意:

  1. 我们得到$param1的值一次,而不是在FLWOR表达式的每次迭代中再次获得。
  2. 我们在let子句而不是for中标识文档,因为我们真的有兴趣迭代所有tei:p元素的序列 period ,而不是每个文档中的tei:p元素
  3. 我们利用eXist的structural index直接下降到tei:p元素,而不是指定任何中间子轴步骤;我们使用XPath祖先轴来达到p的最高/最外部tei: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()。在某些方面,这可以被视为一种风格选择,但在阅读像Evan Lenz的text() is a code smell这样的文章后,当我想获得属性或单个字符串的值时,我更喜欢string()的精度可能包含混合内容的元素的字符串值。 (本文主要涵盖text(),但请参阅评论中对this threaddata()的讨论。)
  6. 我在此处未演示的一个步骤是对您的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