????Mondrian中使用物理的xml文件存储元数据,它的设计者规定了xml文件的格式。下面简单介绍一下它是如何存储元数据的。
Element????Description
根元素
逻辑元素
物理元素
存取控制
其他
??
????
??????
????????
??????
????
????
??????
????????
????????
????????
??????
????
????
????
????
这个模型包含了一个销售cube,这个cube有两个维,时间和性别维;两个度量,销售数量和销售总额。
我们可以在这个模型上写一个 MDX 查询:
select {[Measures].[Unit Sales], [Measures].[Store Sales]} on columns,
??{[Time].[1997].[Q1].descendants} on rows
from [Sales]
where [Gender].[F]
这 个查询涉及到了销售立方体, 每一个维 [Measures], [Time], [Gender], 这些维的多个成员. 结果如下:
[Time]????[Measures].[Unit Sales]????[Measures].[Store Sales]
[1997].[Q1]????0????0
[1997].[Q1].[Jan]????0????0
[1997].[Q1].[Feb]????0????0
[1997].[Q1].[Mar]????0????0
下面详细地介绍一下模式定义:
一个立方体是一个或者多个维和度量的集合,通常是一个事实表,这里是 ‘sales_fact_1997". 事实表保存了需要计算的列和包含维的参考表.
??
度量
销售立方体定义了两个维 "Unit Sales" 和 "Store Sales".
每个度量有一个名字,对应事实表中的一列, 采用一个聚集函数 (usually "sum").
一个可选的格式字符串指定了值如何被打印. 这里我们选择销售数量不带小数的输出(因为销售数量是整数) ,销售总额带2位小数 . 符号',' 和 '.' 是对地区敏感的, 因此如果是在意大利运行, 销售总额可能会出现 "48.123,45". 你可以用 advanced format strings来实现更严格的效果.度量值不是从列中来的,而是从立方体的单元中来的
维
性别维由单一的层次组成,仅有一层。
??
????
??
对于任意给定的销售, 性别维是指购买改产品的客户的性别. 它通过连接事实表"sales_fact_1997.customer_id"和维表"customer.customer_id"
来表示 。"gender" 包括两个值, 'F' 和 'M', 因此性别维包含的成员: [Gender].[F] and [Gender].[M]. 因为 hasAll="true", 系统产生一个特别的 'all' 层, 仅包括一个成员 [All Genders].
一个维可以包含多个层次:
??
????
????
????
??
??
????
????
????
??
第一个层次没有指定名称.缺省的情况下,一个层次拥有和它的维相同的名称。,因此第一个层次成为"Time".这些层次没有太多的共同之处,他们甚至没有相同的表,除非它们连接了实施表中的同一列"time_id"。在一个维上存在两个层次的原因是这样对最终用户是有用的. 如果一个维上存在两个层次, MDX会强制不允许在一个查询中同时用到他们.
A dimension can live in the fact table:
??
????
??????
????
??
??...
??
????
??????
????????
??????????
按照操作对象行的数目来安排次序,表 "product" 的行数最大, 因此它首先出现连接事实表;然后是表 "product_class"和 "product_type",在雪花的末端拥有的行数最小.
注意外部元素
共享维
当为一个连接生成SQL的时候, mondrian 需要知道连接哪一个列. 如果一正在连接一个多表连接, 你需要告诉它连接这些表里的哪一个表,哪一个列.
因为共享维不属于一个cube,你必须给它们一个明确的表 (或者数据源). 当你在一个特别的cube里用他们的时候, 你要指定外键 foreign key. 下面的例子显示了 Store Type 维被 连接到 Sales cube ,用了外键 sales_fact_1997.store_id, 并且被连接到Warehouse cube ,用了外键 warehouse.warehouse_store_id :
??
????
??
??
??
??
虚拟 cubes
父子层次
一个使用方便的层次 有一个严格的层的集合, 成员与层紧密的联系.比如,在 Product 层次中, 任何产品名称层的成员在商标层上都有一个父亲 ,商标层上的成员在产品子目录层也都有一个父亲. 这种结构对于现实世界中的数据有时候太严格了.
一个父子层次只有一层 (不计算 'all' 层), 但是任何成员可以在同一层上有父亲成员. 一个典型的例子是Employees 层次:
??
????
????????parentColumn="supervisor_id" nullParentValue="0">
??????
??????
??????
??????
??????
??????
????
属性 nullParentValue 是指明成员没有父成员的值 。 缺省情况下 nullParentValue="null", 但是因为许多数据库不支持null, 建模时 用其他值来代替空值,0和-1.
物理结构
member reade
member reader 是访问成员的方法. 层次通常以维表为基础建立的 , 因此要用sql来构造.但是甚至你的数据没有存在于 RDBMS, 你可以通过一个 Java 类来访问层次。(自定义 member reader)
Here are a couple of examples:
DateSource (to be written)生成一个时间层次. 按常规,数据仓库工具生成一个表 ,每天包含一行。但是问题是这个表需要装载,并且随着时间的变化能够添加更多的行。 DateSource 在内存中按照要求生成日期成员.
FileSystemSource (to be written) 按照目录和文件的层次描述文件系统。 Like the time hierarchy created by DateSource, this is a virtual hierarchy: the member for a particular file is only created when, and if, that file's parent directory is expanded.
ExpressionMemberReader (to be written) 创建了一个基于表达式的层次。
自定义member reader 必须实现接口 mondrian.rolap.MemberSource. 如果你需要实现一个更大的成员操作集合, 需要实现接口 interface mondrian.rolap.MemberReader; 否则, Mondrian在 mondrian.rolap.CacheMemberReader中封装 你的 reader类.你的 member reader 必须有一个公共的构造函数,这个构造函数拥有参数(Hierarchy,Properties),抛出未检查的错误.
Member readers 用 元素
这是一个例子:
??
????
????
??
Cell readers
类 "com.foo.MyCellReader" 实现了接口interface mondrian.olap.CellReader.
存取控制
可以定义存取控制的属性(角色), 作为模式的一部分, 并且可以在建立连接的时候设置角色。
定义角色
角色可以通过 元素
下面是一个关于角色的例子:
??
????
??????
????????
????????
??????
??????
????????
????????
??????
??????
????
??
元素
元素
元素
你也可以只定义元素