跳转到内容

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 月发布

华夏公益教科书