跳轉到內容

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'};

由 Wolfgang 於 2014 年 4 月釋出

華夏公益教科書