XQuery/資料庫工具
您希望有一套標準化的工具來獲取所有集合和資源的列表,以及與特定模式匹配或具有特定 MIME 型別的資源。
有幾個函式允許您對每個資源(檔案或集合)或僅集合執行快速掃描實用程式函式。這些函式都有兩個引數,一個用於起始集合,另一個是回撥函式,可用於篩選掉不需要的匹配項。
dbutil:scan(xs:anyURI($collection as xs:anyURI, $func as function($collection-path as xs:anyURI, $full-file-path as xs:anyURI?)) as item()*) dbutil:scan-resources($collection as xs:anyURI, $func as function(xs:anyURI) as item()*) dbutil:scan-collections($collection as xs:anyURI), $func as function(xs:anyURI) as item()*) dbutil:find-by-mimetype($collection as xs:anyURI, $mimeType as xs:string) dbutil:find-by-mimetype($collection as xs:anyURI, $mimeType as xs:string, $func as function(xs:anyURI)
這些都是小的 XQuery 函式,可以在以下位置找到
$EXIST_HOME/webapp/WEB-INF/data/expathrepo/shared-0.3.1/content/dbutils.xql
以下示例使用 scan() 函式獲取集合中所有以 'xunit.xq' 字尾結尾的資源的列表 - 這是一個以 XUnit 測試結果格式返回結果的指令碼。
xquery version "1.0";
import module namespace dbutil="http://exist-db.org/xquery/dbutil";
let $root-collection := '/db'
let $file-suffix := 'xunit.xq'
let $find-file-path :=
(: This function MUST have two parameters, the first is the collection path, the second is the FULL path to a resource.
Note that the second parameter must be able to be optional. :)
function($collection as xs:anyURI, $full-path-to-resource as xs:anyURI?) {
if (ends-with($full-path-to-resource, $file-suffix))
then
$full-path-to-resource
else ()
}
return
<results>
{for $resource in dbutil:scan(xs:anyURI($root-collection), $find-file-path)
return
<resource>{$resource}</resource>
}
</results>
<results>
<resource>/db/apps/myapp/unit-tests/scan-xunit.xq</resource>
<resource>/db/apps/myapp/unit-tests/scan-collection-xunit.xq</resource>
</results>
以下示例使用 scan-collection() 函式獲取所有以字串 "/unit-tests" 結尾的集合路徑的列表。
xquery version "1.0";
import module namespace dbutil="http://exist-db.org/xquery/dbutil";
let $root-collection := '/db'
let $leaf-collection-to-find := '/unit-tests'
let $find-leaf-function :=
function($root-collection as xs:anyURI) {
if (ends-with($root-collection, $leaf-collection-to-find))
then
$root-collection
else ()
}
return
<results>
{for $collection in dbutil:scan-collections(xs:anyURI($root-collection), $find-leaf-function)
return
<collection>{$collection}</collection>
}
</results>
<results>
<collection>/db/apps/skos/unit-tests</collection>
<collection>/db/apps/graph2svg/unit-tests</collection>
<collection>/db/apps/eco-meta/unit-tests</collection>
<collection>/db/nosql/unit-tests</collection>
<collection>/db/nosql/apps/make-docx/unit-tests</collection>
<collection>/db/nosql/apps/docbook-to-docx/unit-tests</collection>
</results>
它再次說明了如何透過其 MQL 語言(早於 Sparql)從 Freebase 獲取資訊。
之前的查詢取自
https://developers.google.com/freebase/v1/mql-overview
它限制了從 Freebase API 呼叫中產生的資料。您可以在 API 呼叫中看到一個設定為 3 的限制引數。
https://www.googleapis.com/freebase/v1/mqlread?query=[{"type":"/music/album","name":null,"artist":{"id":"/en/bob_dylan"},"limit":3}]&cursor
如果您沒有在 API 呼叫中指定限制,Freebase 將對您的查詢施加 100 條記錄的限制。此訊息解決了如何獲取所有內容的問題。
實現此目標的關鍵在於上面的 API 呼叫的末尾,它是遊標引數,並且它的使用在此處以示例的形式進行了討論
https://developers.google.com/freebase/v1/mql-overview#querying-with-cursor-paging-results
總而言之,您請求返回一個遊標(有關初始請求的形式,請參見上面的 API 呼叫示例),該遊標充當指向下一組查詢結果的連結。您可以透過提供從先前呼叫返回的遊標的值來獲取下一組。除了下一組之外,您還將獲得另一個指向下一組的遊標。當檢索到最後一組結果時,遊標將返回一個字串值 false(Freebase 概述將此值大寫,但我的程式碼使用小寫 'false',並且這可行)。
概述中提供了示例 Python 程式碼,我還沒有嘗試過或進行嚴格解析,但我相信它呼叫了處理所有遊標的庫。
https://developers.google.com/freebase/v1/mql-overview#looping-through-cursor-results
但是,使用少量的尾遞迴,從 XQuery 也可以輕鬆實現相同的功能。
我們將以一個返回所有電影及其 netflix_id 的 MQL 查詢為例。
[{
"type": "/film/film",
"name": null,
"netflix_id": []
}]
關於 MQL 的一些簡短評論。您可以透過提供欄位名稱和一個值 null 來請求某些內容。Null 將被實際值替換。但是,如果欄位可以具有多個值,MQL 將返回一個數組,並導致您的 null 查詢出錯。即使您希望獲得單個值,也可能發生這種情況,因此您可以透過在上面的查詢中使用空陣列的符號而不是 null 來避免此問題。
您可以將上面的查詢貼上到
http://www.freebase.com/query
中檢視結果(我們將處理程式碼示例中的遊標)。
現在是程式碼,它假設 XQuery 3.0
xquery version "3.0";
import module namespace xqjson="http://xqilla.sourceforge.net/lib/xqjson";
Freebase 返回 JSON,但我們希望將其儲存在 xml 資料庫中,因此我們使用上述軟體包進行 json 到 XML 的轉換。在 eXist 中,您可以透過單擊 eXist 包管理器中的軟體包來安裝軟體包,您可以從 eXist 儀表盤訪問該管理器。
我們為查詢宣告一個變數。
declare variable $mqlQuery {'[{
"type": "/film/film",
"name": null,
"netflix_id": []
}]'};
declare variable $freebase {'https://www.googleapis.com/freebase/v1/mqlread'};
declare variable $key {obtain an API key from freebase and puts it's
value here'};