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