2015-05-09 82 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,不与文件进行修改“_”的

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规范中可用函数的答案,就是要通过解析所有集合内容中的base-uri()函数的结果来筛选collection()函数的结果。例如:

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. 我们得到在FLWOR表达式的每次迭代期间,一次的值为$param1
  2. 我们确定在let条款,而不是for的文件,因为我们是在遍历所有tei:p元素,而不是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(),但看到的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

相关问题