[收藏]Berkeley DB文章集合--关于原生XML数据库指导性的介绍

来源:互联网 发布:大智慧软件官方网站 编辑:程序博客网 时间:2024/06/05 15:40
 
Berkeley DB--关于原生XML数据库指导性的介绍
 
Berkeley DB 介绍

关于原生XML数据库指导性的介绍

法律通知

这个文档按照Sleepycat公共授权规定发布,你能够在http://www.sleepycat.com/download/oslicense.html查看这个授权文档。

Sleepycat
软件,Berkeley DB, Berkeley DB XMLSleepycat LogoSleepycat软件公司的商标或者服务标志,这些标志的版权是保留的,在没有经Sleepycat软件公司明确同意前,不允许第三方使用。

Java(TM)
和所有基于Java的标志是Sun Micorsystems公司在美国和其它国家的商标或者注册商标。

要获取这个文档的原始源代码,请发邮件到:<support@sleepycat.com>.

内容列表

1.
介绍
基本概念
运行Shell
获取帮助
2.XQuery
Berlekey DB XML
加入数据
依靠文档结构查询
值查询
索引介绍
改造结果
排序结果
在多个容器的数据中工作
在特定文档数据中工作
用元数据
修改文档
Schema
约束
Berkeley DB XML API
3.
封装
好处
XML
特征
数据库特征
语言和平台
4.
哪里学习更多
Berkeley DB XML
资源
XML
资源
XQuery
资源

Sleepycat
软件的Berkeley DB XML(BDB XML)是一个嵌入式数据库规范,用来存储和获取XML格式的文档,它建立在成功的Berkeley DB之上, BDB XML支持用XQuery 1.0有效的查询上百万的XML文档。XQuery是设计用来验证和返回XML文档部分数据的查询语言。

本文档介绍BDB XML,以及用BDB XML命令行介绍一下它的一些特征。这是一个高层次的介绍,提供关于系统能做什么以及它如何应用到你的项目的一些基本介绍。本文档不是详细指南和参考手册,所以我们将省略技术细节,着重于用BDB XML能够做什么事情。你应该熟悉XMLXQuery基本概念。依照本文档,你能够用BDB XML shell来运行例子,并且很快熟悉BDB XML的能力。

第一章. 介绍
内容列表
基本概念
运行Shell
获取帮助

欢迎来到Berkeley DB XML(BDB XML),一个提供XQuery查询支持的原生XML数据库(NXD)引擎。这个文档将向你介绍BDB XML的特征。在读完这篇文档之后,你应该非常清楚BDB XML能为你做什么,并且知道如何在你的系统和应用程序中如何用它来管理数据。

基本概念

典型的,BDB XML是一个库,直接联结到你的程序中,另外,BDB XML有一个命令行工具Shell,允许你与BDB XML交互,而不用通常使用的程序语言。你能够将Shell作为你的应用程序的一部分,当作一个管理工具,或者简单的解释产品特征工具。

BDB XML中,所有XML数据是存储在叫做容器的文件中,BDB XML Shell提供一个简单和方便的方法在这些容器中工作,并用友好的,交互式的环境暴露大多数BDB XML的功能,而不需要用程序语言。

允许Shell
Shell
命令定位在<BDB XML安装目录>/bin目录,名字未dbxml.
要运行shell,简单的在你的操作系统的命令行输入dbxml。假设你在操作系统命令行路径中包含dbxml shell,那么你将看到dbxml>提示。

user>dbxml
dbxml>

在后面的例子中,你将看到dbxml>提示后跟你要输入的命令,许多命令是简单的一行。可是,复杂的XQuery例子将分成多行。每个例子将展示输入的命令和输出结果。当输出太长时,省略号(...)将被用来代替中间结果。

当用BDB XML,你将发现文档内容时存储在一个容器中,这是BDB XML的第一个基本概念:容器装载XML文档。在一个容器中的文档可能也可能不共享同样的schema

要开始探索BDB XML,建立一个容器。我们第一个例子模型是一个简单的电话本数据库。容器名称将是phone.dbxml

dbxml>createContainer phone.dbxml

Creating document storage container

上面的命令和输出是非常简单的。它仅仅确认命令行的执行。注意文件phone.dbxml的文件将会在你的工作目录建立。这是一个新的文档存储容器。容器装载XML数据,索引,文档元数据,和一些其它有用的信息,全部通过BDB XML管理。不要直接编辑容器,总是应该用BDB XML库来管理它。'.dbxml'扩展帮助你标识这是BDB XML数据库,但是这只是一个命名习惯,而不是严格的需求。

注意
除建立一个容器之外,BDB XML shell也自动的打开它,并且让它做好使用的准备。

电话本例子的数据模型用下列格式的XML项:
<phonebook>
    <name>
        <first>Tom</first>
        <last>Jones</last>
    </name>   
    <phone type="home">420-203-2032</phone>
</phonebook>

现在按下面格式加入新的电话本项到容器中:
dbxml> putDocument phone1 '<phonebook>
    <name>
        <first>Tom</first>
        <last>Jones</last>
    </name>   
    <phone type="home">420-203-2032</phone>
</phonebook>' s

Document added, name = phone1

dbxml> putDocument phone2 '<phonebook>
    <name>
        <first>Lisa</first>
        <last>Smith</last>
    </name>   
    <phone type="home">420-992-4801</phone>
    <phone type="cell">390-812-4292</phone>
</phonebook>' s

Document added, name = phone2

注意
XML
文档内容是封装在一对单引号中,并且命令用s字符中断。这表示我们用字符串加入新文档。单引号是用在那些需要包含空格或者需要劈分到多行的命令参数中。

现在容器有了一些电话本项,下面的例子演示一些基于XPath语句的基本XQuery查询,后续的章节我们将演示更复杂的XQuery语句。

注意
XPath
是一个XQuery规范的一个重要部分。它的功能就象SELECT语句在SQL中一样。它本质上是用来表示数据集中的数据子集。

要获取存储在容器中的last names:
dbxml> query '
collection("phone.dbxml")/phonebook/name/last/text()'

2 objects returned for eager expression '
collection("phone.dbxml")/phonebook/name/last/text()'

dbxml> print
Jones
Smith            

要查找Lisa的家庭电话号码:
dbxml> query '
collection("phone.dbxml")/phonebook[name/first = "Lisa"]/phone[@type =
"home"]/text()'

1 objects returned for eager expression '
collection("phone.dbxml")/phonebook[name/first = "Lisa"]/phone[@type =
"home"]/text()'

dbxml> print
420-992-4801

要查找420区号的电话号码:
dbxml> query '
collection("phone.dbxml")/phonebook/phone[starts-with(., "420")]/text()'

2 objects returned for eager expression '
collection("phone.dbxml")/phonebook/phone[starts-with(., "420")]/text()'

dbxml> print
420-203-2032
420-992-4801

这些查询简单的获取数据子集,就像关系数据库中的SELECT语句。每个查询由两部分构成,第一部分要检查的文档集。这是通过象XQuery的导航函数 collection()完成的。这个例子中,collection("phone.dbxml")指定我们想应用我们查询的容器。第二个部分是一个 XPath语句。第一个例子的XPath语句是/phonebook/name/last/text(),基于我们的文档结构,将返回所有last name,并且用文本表示它们。

理解XPath是理解XQuery的第一步。

获取帮助
BDB XML Shell
有一个内置的帮助,简单的在命令行输入help
dbxml> help

Command Summary
---------------

#                -
注释。不做任何事情
abort            -
终端当前的事务
addAlias         -
加入一个别名到默认容器
addIndex         -
加入一个索引到默认容器
append           -
在查询表达式中添加节点规范
commit           -
提交当前的事务, 并且开始一个新的事务
contextQuery     -
用最后的结果当作上下文执行查询表达式
cquery           -
在默认容器的上下文中执行一个查询表达式
createContainer  -
建立一个新容器,它将变成默认的容器
debug            -
调试命令 -- 仅内部使用
delIndex         -
从默认的容器中删除一个索引
getDocuments     -
从默认容器中通过名称得到文档
getMetaData      -
从命名的文档中得到元数据
help             -
打印帮助信息,'help commandName'获得扩展帮助
info             -
在默认容器上得到信息
insertAfter      -
在通过查询表达式选择的节点后面插入新的内容
insertBefore     -
在通过查询表达式选择的节点前面插入新的内容
listIndexes      -
列出在默认容器中的所有索引
lookupIndex      -
在默认的容器中执行索引查询
lookupStats      -
在默认容器上查询索引统计
openContainer    -
打开一个容器,并用它作为默认的容器
preload          -
预加载(打开)一个容器
print            -
打印最新的结果
putDocument      -
插入文档到默认容器中
query            -
XmlManager上下文中执行一个表达式
queryPlan        -
打印为指定的查询表达式的查询计划
quit             -
退出程序
removeAlias      -
从默认容器中删除一个别名
removeContainer  -
删除一个容器
removeDocument   -
从默认容器中删除一个文档
removeNodes      -
从通过查询表达式指定的文档中删除内容
renameNodes      -
重命名通过查询表达式指定的节点
run              -
将指定的文件当作脚本运行
setApplyChanges  -
在默认更新上下文中修改 "apply changes" 状态
setBaseUri       -
在默认上下文中设置基本uri
setLazy          -
在默认上下文中设置lazy评估开或关
setMetaData      -
为指定的文档设置元数据
setNamespace     -
在默认上下文中建立一个prefix->namespace绑定
setReturnType    -
在默认上下文中设置返回类型
setTypedVariable -
在默认上下文中设置变量为指定的类型
setVariable      -
在默认上下文中设置一个变量
setVerbose       -
设置本shell的冗长
transaction      -
为所有后续操作建立一个事务
updateNodes      -
基于查询表达式和新内容更新节点上下文
upgradeContainer -
更新一个容器到当前的容器格式

任何给的的命令有附加的详细帮助。例如:
dbxml> help createContainer

createContainer --
建立一个新容器,它将变成默认的容器

使用方法: createContainer <containerName> [n|in|d] [[no]validate]
建立一个新的默认容器;旧的默认容器被关闭。
第二个参数'd'建立一个完整文档存储容器(默认)
第二个参数'n'建立一个节点存储容器,并且'in'DBXML_INDEX_NODES建立一个节点存储容器。
可选的第三个参数表示是否在插入时验证文档。
""
containerName建立一个in-memory容器。
这个命令用XmlManager::createContainer()方法。

帮助文本是关于命令和实现这个命令的API调用有价值的信息。这帮助你去查找API文档中更详细的相关章节,也是一个探索在交互式方式调用API的公共用法。

第二章. XQueryBerkeley DB XML

内容列表

加入数据
依靠文档结构查询
值查询
索引介绍
改造结果
用多个容器的数据工作
用指定文档的数据工作
用元数据
修改文档
schema
容器
Berkeley DB XML API

这节介绍一些BDB XML提供的XQuery功能,然后介绍一些BDB XML提供的,让在XML上高效工作的功能,不熟悉XQuery的应该首先查看一下在本文档后面列出的极好的XQuery指南。

加入数据
这这个例子中,容器将管理有几千个文档的虚拟数据库parts。开始用下面的命令建立一个容器叫做parts.dbxml:

dbxml> createContainer parts.dbxml

Creating document storage container

成功的响应表示容器在磁盘上建立了,打开了,并且在shell的上下文中变成默认的容器了。下一步让容器具有3000个下面基本结构的XML文档:

<part number="999">
    <description>Description of 999</description>
    <category>9</category>
</part>

一些文档提供额外的复杂度,有下面的结构:
<part number="990">
   <description>Description of 990</description>
   <category>0</category>
   <parent-part>0</parent-part>
</part>

用下面的putDocument命令插入例子数据到新parts容器中。
dbxml> putDocument "" '
for $i in (0 to 2999)
return
  <part number="{$i}">
    <description>Description of {$i}</description>
    <category>{$i mod 10}</category>
    {
      if (($i mod 10) = 0)
      then <parent-part>{$i mod 3}</parent-part>
      else ""
    }
  </part>' q

依靠文档结构查询
注意parts容器能够包含不同结构的文档。管理灵活结构的数据数据能力是XML和关系数据库基本原理的区别之一。在这个例子中,单个容器管理两个共享某些元素的不同结构文档。实际上,文档部分的重叠允许有效的查询和公共的索引。这能够用来联合关系数据。结构化查询使用在XML数据中这样的原生联合。这是一些例子结构化查询。

首先选择所有在它们的文档结构中包含parent-part节点的part记录,在英文中,跟随在XQuery之后的将读为:"from the container named parts select all part element that also contain a parent-part element as a direct child of the element".XQuery代码为:

dbxml> query '
collection("parts.dbxml")/part[parent-part]'

300 objects returned for eager expression '
collection("parts.dbxml")/part[parent-part]'

要检测结果,用print命令

dbxml> print
<part number="540"><description>Description of 540</description>
<category>0</category><parent-part>0</parent-part></part>
<part number="30"><description>Description of 30</description>
<category>0</category><parent-part>0</parent-part></part>
...
<part number="990"><description>Description of 990</description>
<category>0</category><parent-part>0</parent-part></part>
<part number="480"><description>Description of 480</description>
<category>0</category><parent-part>0</parent-part></part>

要仅仅显示parent-part元素,而不显示文档的其余部分,仅些微的修改查询:

dbxml> query '
collection("parts.dbxml")/part/parent-part'

300 objects returned for eager expression '
collection("parts.dbxml")/part/parent-part'

dbxml> print
<parent-part>0</parent-part>
<parent-part>0</parent-part>
...
<parent-part>2</parent-part>
<parent-part>2</parent-part>

作为选择,要获取parent-part元素的值,查询变成:
dbxml> query '
collection("parts.dbxml")/part/parent-part/text()'

300 objects returned for eager expression '
collection("parts.dbxml")/part/parent-part/text()'

dbxml> print
0
0
...
2
2

转化先前的例子来选择所有没有parent-part元素的文档:

dbxml> query '
collection("parts.dbxml")/part[not(parent-part)]'

2700 objects returned for eager expression '
collection("parts.dbxml")/part[not(parent-part)]'

dbxml> print
<part number="22"><description>Description of 22</description>
<category>2</category></part>
<part number="1995"><description>Description of 1995</description>
<category>5</category></part>
...
<part number="2557"><description>Description of 2557</description>
<category>7</category></part>
<part number="2813"><description>Description of 2813</description>
<category>3</category></part>

除了随着时间的过去容易表达和管理之外,结构化查询有时象关系结合。有些结构化用大多传统的关系数据库去模仿甚至是不可能或者不切实际的。这部分归功于原生 XML格式是自描述的,也是灵活的,表现数据的。本质上,关系是在XML结构本身隐含的表示。当你开始用基于值的查询组合结构化查询时,这个功能是很显著的。

值查询
XQuery
可以基于值查找数据,下面的例子组合结构化查询和在返回结果中在值上进行限制:
要选择有parent-part孩子,并且parent-part等于1的所有parts

dbxml> query '
collection("parts.dbxml")/part[parent-part = 1]'  

100 objects returned for eager expression '
collection("parts.dbxml")/part[parent-part = 1]'

注意这个查询除了用'[parent-part = 1]'之外,和前面的一样,结果为:

dbxml> print
<part number="1840"><description>Description of 1840</description>
<category>0</category><parent-part>1</parent-part></part>
<part number="1330"><description>Description of 1330</description>
<category>0</category><parent-part>1</parent-part></part>
...
<part number="1300"><description>Description of 1300</description>
<category>0</category><parent-part>1</parent-part></part>
<part number="790"><description>Description of 790</description>
<category>0</category><parent-part>1</parent-part></part>

XQuery
也提供全部集合的表达式,你能够用来从容器中选择文档,例如,如果我们想查询part数字为10701032parts,我们能够运行下面的查询:
注意
这个查询是基于属性值查询,而不是元素值,这是查询文档同样有效的方法。

dbxml> query '
collection("parts.dbxml")/part[@number = 1070 or @number = 1032]'

2 objects returned for eager expression '
collection("parts.dbxml")/part[@number = 1070 or @number = 1032]'

dbxml> print
<part number="1070"><description>Description of 1070</description>
<category>0</category><parent-part>2</parent-part></part>
<part number="1032"><description>Description of 1032</description>
<category>2</category></part>

标准的不平等操作和其它表达式也有效帮助隔离请求在容器中的子集数据:

dbxml> query '
collection("parts.dbxml")/part[@number > 100 and @number < 105]'

4 objects returned for eager expression '
collection("parts.dbxml")/part[@number > 100 and @number < 105]'

dbxml> print
<part number="101"><description>Description of 101</description>
<category>1</category></part>
<part number="102"><description>Description of 102</description>
<category>2</category></part>
<part number="103"><description>Description of 103</description>
<category>3</category></part>
<part number="104"><description>Description of 104</description>
<category>4</category></part>

索引介绍

现代原生XML数据库的一个主要优势是它们能够索引它们包含的XML文档,正确的使用索引能够显著的减少特定查询需求的时间,执行前面的例子可能需要能够感觉到的时间,这是因为BDB XML将在容器的每个文档上评估查询。没有索引,BDB XML没有选择,只好依次查看每个文档,用索引,BDB XML能够用单个,或者显著减少的集合来匹配文档子集,通过小心的使用BDB XML索引策略,我们能够显著的改进获取性能。

为了验证我们索引的有效性,我们首先在shell中提高verbosity的级别:
dbxml> setVerbose 2 2

注意
下面的查询执行时间是与作者的电脑和操作系统相关的,你的查询时间将依赖你的系统品质而不同。可是,改进查询时间的百分比应该是相对的类似。

重新调用前面的结构化查询:

query '
collection("parts.dbxml")/part[parent-part]'

Query      - Starting eager query execution
Query      - parts.dbxml - U : [3000] 256 512 768 1024 1280 1536 1792 2048
2304 2560 2816 257 513 769 1025 1281 1537 1793 2049 2305 ...
Query      - Finished eager query execution, time taken = 2495.82ms
300 objects returned for eager expression '
collection("parts.dbxml")/part[parent-part]'

注意查询执行时间,这个查询用了几乎2.5秒来执行,这是因为查询是依次检查每个文档。为了改进我们的性能,我们想指定一个索引允许BDB XML去识别包含parent-part元素的文档子集,而不是检查每个文档。

索引有4个部分:路径类型,节点类型,关键字类型,和唯一性。查询需要一个节点元素索引来决定某些东西是否出现。因为模式不是期望唯一的,我们不想打开唯一性,因此,我们应该用的BDB XML索引类型为node-element-presence-none

dbxml> addIndex "" parent-part node-element-presence-none
Adding index type: node-element-presence-none to node: {}:parent-part

dbxml> query '
collection("parts.dbxml")/part[parent-part]'

Query      - Starting eager query execution
Query      - parts.dbxml - P(parent-part) : [300] 2 12 22 32 42 52 62 72 82 92
102 112 122 132 142 152 162 172 182 192 ...
Query      - Finished eager query execution, time taken = 173.084ms
300 objects returned for eager expression '
collection("parts.dbxml")/part[parent-part]'

我们的查询时间从2.5秒到了1/5秒,随着容器大小和复杂性的增长,索引增加的性能更显著。

前面的索引也将改进设计为parent-part元素的值查询性能。

dbxml> query '
collection("parts.dbxml")/part[parent-part = 1]'

Query      - Starting eager query execution
Query      - parts.dbxml - P(parent-part) : [300] 2 12 22 32 42 52 62 72 82 92
102 112 122 132 142 152 162 172 182 192 ...
Query      - Finished eager query execution, time taken = 223.821ms
100 objects returned for eager expression '
collection("parts.dbxml")/part[parent-part = 1]'

这个查询也从2.4秒到仅仅1/5秒,因为我们验证节点内容依靠数字,通过索引节点为10进制值,我们能够让查询执行时间更少。要这样做,用:

node-element-equality-decimal.

dbxml> addIndex "" parent-part node-element-equality-decimal

Adding index type: node-element-equality-decimal to node: {}:parent-part

dbxml>  query '
collection("parts.dbxml")/part[parent-part = 1]'

Query      - Starting eager query execution
Query      - parts.dbxml - V(parent-part,=,'1') : [100] 12 42 72 102 132 162
192 222 252 282 312 342 372 402 432 462 492 522 552 582 ...
Query      - Finished eager query execution, time taken = 69.803ms
100 objects returned for eager expression '
collection("parts.dbxml")/part[parent-part = 1]'
 
用第二个索引,查询运行少于1/10秒。

额外的索引将改进其它值查询的性能:

dbxml>  query '
collection("parts.dbxml")/part[@number > 100 and @number < 105]'

Query      - Starting eager query execution
Query      - parts.dbxml - U : [3000] 256 512 768 1024 1280 1536 1792 2048
2304 2560 2816 257 513 769 1025 1281 1537 1793 2049 2305 ...
Query      - Finished eager query execution, time taken = 6938.48ms
4 objects returned for eager expression '
collection("parts.dbxml")/part[@number > 100 and @number < 105]'

几乎7秒,还有许多空间可以改进。要改进我们的区域查询,我们能够为数字属性提供一个索引:

dbxml>  addIndex "" number node-attribute-equality-decimal

Adding index type: node-attribute-equality-decimal to node: {}:number

dbxml> query '
collection("parts.dbxml")/part[@number > 100 and @number < 105]'

Query      - Starting eager query execution
Query      - parts.dbxml - V(@number,>,'100') : [2899] 103 104 105 106 107
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 ...
Query      - parts.dbxml - V(@number,<,'105') : [105] 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20 21 ...
Query      - parts.dbxml - n(V(@number,>,'100'),V(@number,<,'105')) : [4]
103 104 105 106
Query      - Finished eager query execution, time taken = 29.967ms
4 objects returned for eager expression '
collection("parts.dbxml")/part[@number > 100 and @number < 105]'

这个查询执行时间减少到1/10秒,正确的使用索引能够戏剧性的改进查询性能。

BDB XML
提供各种不同类型的索引来改进查询性能。

改造结果
当改造XML内容时,XQuery也是有用的,这个特征的一个通用方法是重新构造数据到XHTML显示到Web浏览器中。

再次用前面见到的例子,修改它用XQuery产生一个XHTML版本的结果显示到Web浏览器中:
dbxml> query '<html><body>
    <ul>
        {
        for $part in
            (collection("parts.dbxml")/part[@number > 100 and @number < 105])
        return
            <li>{$part/description/text()}</li>
        }
    </ul></body></html>'

Query      - Starting eager query execution
Query      - parts.dbxml - V(@number,>,'100') : [2899] 103 104 105 106 107
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 ...
Query      - parts.dbxml - V(@number,<,'105') : [105] 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21 ...
Query      - parts.dbxml - n(V(@number,<,'105'),V(@number,>,'100')) : [4]
103 104 105 106
Query      - Finished eager query execution, time taken = 22.561ms
1 objects returned for eager expression '<html><body>
    <ul>
        {
        for $part in
            (collection("parts.dbxml")/part[@number > 100 and @number < 105])
        return
            <li>{$part/description/text()}</li>
        }
    </ul></body></html>'
   
dbxml> print
<html><body><ul>
<li>Description of 101</li>
<li>Description of 102</li>
<li>Description of 103</li>
<li>Description of 104</li>
</ul></body></html>

这个XQuery引入XQuery FLWOR表达式(For, Let, While, Order by, Return -- 有时写成FLWR或者FLOWR),注意XPath总是在查询中使用.可是现在,它是全部FLWOR结构的一部分.

注意
为了在动态Web站点显示而处理容器中XML数据最好通过合适的语言,而不应该用命令行工具.

FLWOR中的'O'是排序, 前面的XQuery没有包含明确的排序指令,因此将按照它们在容器中的顺序出现.随着时间的过去,文档的改变,数据不会保持在不变的次序.XQuery语句中加入一个明确的次序可以实现严格的排序.

dbxml> query '<html><body>
    <ul>
        {
        for $part in
            (collection("parts.dbxml")/part[@number > 100 and @number < 105])
        order by xs:decimal($part/@number) descending
        return
            <li>{$part/description/text()}</li>
        }
    </ul></body></html>'

Query      - Starting eager query execution
Query      - parts.dbxml - V(@number,>,'100') : [2899] 103 104 105 106 107
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 ...
Query      - parts.dbxml - V(@number,<,'105') : [105] 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21 ...
Query      - parts.dbxml - n(V(@number,<,'105'),V(@number,>,'100')) : [4]
103 104 105 106
Query      - Finished eager query execution, time taken = 29.869ms
1 objects returned for eager expression '<html><body>
    <ul>
        {
        for $part in
            (collection("parts.dbxml")/part[@number > 100 and @number < 105])
        order by $part/@number descending
        return
            <li>{$part/description/text()}</li>
        }
    </ul></body></html>'

dbxml> print
<html><body><ul>
<li>Description of 104</li>
<li>Description of 103</li>
<li>Description of 102</li>
<li>Description of 101</li>
</ul></body></html>

parts
现在安装期望的次序出现.

在多个容器的数据中工作
一个应用程序可以用一个或者多个容器.BDB XMLXQuery为这个解决方案提供明确的支持.首先,建立第二个容器,并加入一些数据.少量的简单文档足够演示这个特征.开始,我们加入它们到新容器:

dbxml> createContainer components.dbxml

Creating document storage container

dbxml> putDocument component1 '<component number="1">
<uses-part>89</uses-part>
<uses-part>150</uses-part>
<uses-part>899</uses-part>
</component>'

Document added, name = component1

dbxml> putDocument component2 '<component number="2">
<uses-part>901</uses-part>
<uses-part>87</uses-part>
<uses-part>189</uses-part>
</component>'

Document added, name = component2

dbxml> preload parts.dbxml

dbxml> preload components.dbxml

这些新的文档用来表示一个由几个前面定义的parts组成的巨大的组件.要输出所有组件和它们交叉容器关联部分的XHTML视图,:

dbxml> query '<html><body>
  <ul>
    {
      for $component in collection("components.dbxml")/component
      return
        <li>
          <b>Component number: {$component/@number/text()}</b><br/>
          {
            for $part-ref in $component/uses-part
            return                   
              for $part in collection("parts.dbxml")/part[@number =
                $part-ref cast as xs:decimal]
              return
                <p>{$part/description/text()}</p>
          }               
        </li>
    }
  </ul>
</body></html>'

Query      - Starting eager query execution
Query      - components.dbxml - U : [2] 2 3
Query      - parts.dbxml - V(@number,=,'89') : [1] 91
Query      - parts.dbxml - V(@number,=,'150') : [1] 152
Query      - parts.dbxml - V(@number,=,'899') : [1] 901
Query      - parts.dbxml - V(@number,=,'901') : [1] 903
Query      - parts.dbxml - V(@number,=,'87') : [1] 89
Query      - parts.dbxml - V(@number,=,'189') : [1] 191
Query      - Finished eager query execution, time taken = 19.495ms
1 objects returned for eager expression '<html><body>
  <ul>
    {
      for $component in collection("components.dbxml")/component
      return
        <li>
          <b>Component number: {$component/@number/text()}</b><br/>
          {
            for $part-ref in $component/uses-part
            return                   
              for $part in collection("parts.dbxml")/part[@number =
                $part-ref cast as xs:decimal]
              return
                <p>{$part/description/text()}</p>
          }               
        </li>
    }
  </ul>
</body></html>'

注意
这个查询将用我们前面建立的索引优势.XQuery指派变量$part-ref为一般的XPath数字类型.我们前面定义的索引是比数字更特殊的类型10进制值.要获得用这个索引的查询,我们需要通过用cast as xs:decimal子句提供一些辅助查询优化.这提供关于我们比较数据更特殊的类型信息.如果我们不用它,查询不能用十进制索引,这是因为XQuery 用的类型和索引类型不匹配.

查询的输出,重新格式化为可读的,:

dbxml> print
<html><body>
    <ul>
        <li>
            <b>Component number: 1</b><br/>
            <p>Description of 89</p>
            <p>Description of 150</p>
            <p>Description of 899</p>
        </li>
        <li>
            <b>Component number: 2</b><br/>
            <p>Description of 901</p>
            <p>Description of 87</p>
            <p>Description of 189</p>
        </li>
    </ul>
</body></html>

BDB XML
容器模型提供大量的灵活性,因为这里没有指定的XML schema与容器关联. 不同结构的XML文档能够在单个容器中共存. 作为选择,分开的容器能够包括概念上相同的XML文档, 或者其它用途. 容器和文档组织可以更加你的程序的需要进行裁减.

在指定文档数据上工作

前面的查询依靠所有在容器中的文档工作.但是有一种情况的目标是在单个文档中访问数据,基于我们给定的名称隔离单个文档是可能的,然后依靠它执行XQuery表达式.

例如,要从容器components.dbxml中叫做componment1的文档中选择数字属性:

dbxml> query '
doc("components.dbxml/component1")/component/@number'

Query      - Finished eager query execution, time taken = 2.774ms
1 objects returned for eager expression '
doc("components.dbxml/component1")/component/@number'

dbxml> print
{}number="1"

注意
doc
函数能够用来访问外部任意BDB XML管理的容器.例如,要整合在HTTP上返回XMLWeb服务,doc函数执行web服务,然后用结果数据当作XQuery查询的一部分.

一个web服务有能力查询特定部分的价格,当作单个XQuery FLWOR整合到一个HTML页面.Sleepycat设置了这样的模拟服务来支持例子. 有一个XML文档在xml.sleepycat.com通过web服务提供.可以用XQuery中的doc函数访问价格数据.价格文件的URL http://xml.sleepycat.com/intro2xml/prices.xml. 文件的内容将提供parts的价格.

http://xml.sleepycat.com/intro2xml/prices.xml
的内容看起来象这样:

<prices>
    <part number="87">29.95</part>
    <part number="89">19.95</part>
    <part number="150">24.95</part>
    <part number="189">5.00</part>
    <part number="899">9.95</part>
    <part number="901">15.00</part>
</prices>

当那个完成后,我们能够增强我们前面的parts查询来为所有parts加入价格.同时,我们也将转换为用HTML表格来显示数据.

dbxml> query '<html><body>
  <ul>
    {
      for $component in collection("dbxml:components.dbxml")/component
      return
        <li>
          <b>Component number: {$component/@number/text()}</b><br/>
          <table>
          {
            for $part-ref in $component/uses-part
            return                   
              for $part in collection("dbxml:parts.dbxml")/part[@number =
                    $part-ref cast as xs:decimal]
                return                           
                <tr><td>{$part/description/text()}</td>
                <td>{
                  doc("http://xml.sleepycat.com/intro2xml/prices.xml")//part[
                        @number = $part/@number]/text()                           
                }</td></tr>
         }               
         </table>
      </li>
    }
  </ul>
</body></html>'

Query      - Starting eager query execution
Query      - components.dbxml - U : [2] 2 3
Query      - parts.dbxml - V(@number,=,'89') : [1] 91
Query      - parts.dbxml - V(@number,=,'150') : [1] 152
Query      - parts.dbxml - V(@number,=,'899') : [1] 901
Query      - parts.dbxml - V(@number,=,'901') : [1] 903
Query      - parts.dbxml - V(@number,=,'87') : [1] 89
Query      - parts.dbxml - V(@number,=,'189') : [1] 191
Query      - Finished eager query execution, time taken = 55.011ms
1 objects returned for eager expression '<html><body>
  <ul>
    {
      for $component in collection("dbxml:components.dbxml")/component
      return
        <li>
          <b>Component number: {$component/@number/text()}</b><br/>
          <table>
          {
            for $part-ref in $component/uses-part
            return                   
              for $part in collection("dbxml:parts.dbxml")/part[@number =
                    $part-ref cast as xs:decimal]
                return                           
                <tr><td>{$part/description/text()}</td>
                <td>{
                  doc("http://xml.sleepycat.com/intro2xml/prices.xml")//part[
                        @number = $part/@number]/text()                           
                }</td></tr>
         }               
         </table>
      </li>
    }
  </ul>
</body></html>'

结果是为可读性格式化:

dbxml> print
<html>
    <body>
        <ul>
            <li>
                <b>Component number: 1</b>
                <br/>
                <table>
                    <tr>
                        <td>Description of 89</td>
                        <td>19.95</td>
                    </tr>
                    <tr>
                        <td>Description of 150</td>
                        <td>24.95</td>
                    </tr>
                    <tr>
                        <td>Description of 899</td>
                        <td>9.95</td>
                    </tr>
                </table>
            </li>
            <li>
                <b>Component number: 2</b>
                <br/>
                <table>
                    <tr>
                        <td>Description of 901</td>
                        <td>15.00</td>
                    </tr>
                    <tr>
                        <td>Description of 87</td>
                        <td>29.95</td>
                    </tr>
                    <tr>
                        <td>Description of 189</td>
                        <td>5.00</td>
                    </tr>
                </table>
            </li>
        </ul>
    </body>
</html>

从外部BDB XML获得部分数据当作从web服务或者其它来源query的一部分的能力在建立应用程序时提供极大的能力和灵活性.

用元数据

元数据时关于数据的数据,就是说,它提供关于文档的附加信息,而不是文档的真实部分.例如,加入到components.dbxml容器的文件将给出一个名称.每个名称表示关于每个独立文档的元数据.元数据的其它使用可能包括文档修改时间或者修改它的私人名称.另外有一种情况是当修改真实文档不可能时,需要附加数据跟踪想得到的关于文档信息.例如,你可能需要跟踪哪个用户最后改变了容器中的文档,并且你可能需要在不修改文档本身的情况下完成.为了这个理由, BDB XML存储元数据和文档分开,还是允许你依靠元数据执行索引查询,就像它是文档的一部分.

要加入定制元数据到文档,setMetaData命令.

dbxml> openContainer components.dbxml

dbxml> setMetaData component1 '' modifyuser string john                           

MetaData item 'modifyuser' added to document component1

dbxml> setMetaData component2 '' modifyuser string mary

MetaData item 'modifyuser' added to document component2

元数据本质上包含在它自己的,唯一的名字空间(dbxml:metadata).所以依靠元数据查询需要指明这个名字空间:

dbxml> query '
collection("components.dbxml")/component[dbxml:metadata("modifyuser")="john"]'

1 objects returned for eager expression '
collection("components.dbxml")/component[dbxml:metadata("modifyuser")="john"]'

dbxml> print
<component number="1">
<uses-part>89</uses-part>
<uses-part>150</uses-part>
<uses-part>899</uses-part>
</component>

注意元数据没有出现在结果文档中,元数据不是文档的一部分;它仅仅在容器中存在,并且与特定的文档关联.如果你从BDB XML得到文档,然后传输到其它系统,将不会包括元数据.当你需要包含文档额原始状态时,也想跟踪一些它存储在BDB XML中时的附加信息时,这是很有用的.

修改文档
XQuery
语言没有定义修改存储在XML数据库中文档的任何方法.BDB XML将加入对这个功能的支持,其间,BDB XML没有包含很好的API来修改文档.用这个API可能加入新的数据到存在的文档,修改(替换)文档中存在的数据,和从文档中删除数据.

BDB XML Shell,修改需要两步,首先,你选择需要修改的文档,在本例中仅选择了componment1:

dbxml> query doc('components.dbxml/component1')

1 objects returned for eager expression 'doc('components.dbxml/component1')'

第二,指定对结果的修改,对于我们的例子,有很多可能的修改操作,我们简单的加入一个新的'uses-parts'元素到文档中:

dbxml> append ./component element uses-part '12'

Appending into nodes: ./component an object of type: element with name:
uses-part and content: 12

1 modifications made.

dbxml> print
<?xml version="1.0" encoding="UTF-8" standalone="no" ?><component number="1">
<uses-part>89</uses-part>
<uses-part>150</uses-part>
<uses-part>899</uses-part>
<uses-part>12</uses-part></component>

append
命令与前面的查询上下文相关,因为我们用doc函数选择它,所以它包含完整的componment1文档.
 
原创粉丝点击