开源中文网

您的位置: 首页 > 数据库应用 > Berkeley DB > 正文

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

来源:  作者:

这个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文档.

Tags:Berkeley DB XML数据库
关于开源中文网 - 联系我们 - 广告服务 - 网站地图 - 版权声明