2015-05-09 108 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

相關問題