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

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

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

法律通知

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

Sleepycat
软件 ,Berkeley DB, Berkeley DB XML Sleepycat Logo Sleepycat 软件公司的商标或者服务标志,这些标志的版权是保留的 , 在没有经 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 能够做什么事情。你应该熟悉 XML XQuery 基本概念。依照本文档,你能够用 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 的公共用法。

第二章 . XQuery Berkeley 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 数字为 1070 1032 parts ,我们能够运行下面的查询:
注意
这个查询是基于属性值查询,而不是元素值,这是查询文档同样有效的方法。

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 XML XQuery 为这个解决方案提供明确的支持 . 首先 , 建立第二个容器 , 并加入一些数据 . 少量的简单文档足够演示这个特征 . 开始 , 我们加入它们到新容器 :

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 上返回 XML Web 服务 , 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 文档 .
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值