`
jbf034
  • 浏览: 153212 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

“聚合”(Aggregation)

阅读更多
数据库列有个带限制的类型集: integers, strings, dates, 等等。典型地,我们的应
用程序却有很多类型—我们用类定义来表现我们代码的抽象。更好的事是,如果我们能够映
射数据库内的一些列信息到我们的高级抽象中—我们以同样方式包装行数据本身在“模型”
对象中。

例如,customer 表数据可能包括用于存储消费者姓名的列—或许是姓,名,称呼。在我
们的程序内,我们想包装这些与名字有关的列到一个单独的Name 对象中;三个列被映射到一
个单独的Ruby 对象中,与其它所的customer 表字段一同包含在消费者“模型”中。而且,在我们回头写“模型”时,我们希望从Name 对象抽取数据并放回到数据库内相应的三个列中。这种功能被称为聚合(aggregation)(尽管有人称它为合成(composition)—这依赖于你是从上往下,还是从下往上看它。)并不奇怪,“活动记录”做到这些很容易。你定义一类来持有数据,并且你添加一个声明给“模型”类来告诉它映射数据库的列给持有数据类的对象,当然也可以从这个对象获取列数据。
持有合成数据的类(是例子中的Name 类)必须遵循两个标准。

首先,它必须有一个构造函数,它将接受数据库内列的数据,一个参数对应一个列。

其次,它必须提供能返回这个值的属性,一个属性对应一个列。在内部,它可以存储它需要使用的任何形式的数据,只要它能双向映射列数据。

对于我们name 例子,我们将定义一个简单的类,它持有三个合成部分做为实例变量。我
们也定义to_s()方法来格式化完整的名字为一个字符串。

class Name
attr_reader :first, :initials, :last
def initialize(first, initials, last)
@first = first
@initials = initials
@last = last
end
def to_s
[ @first, @initials, @last ].compact.join(" ")
end
end

现在们必须告诉我们的Customer“模型”类,有三个数据库的列first_name, initials,
和last_name 应该被映射到Name 对象中。我们用composed_of 声明来完成。

尽管composed_of 可以只用一个参数来调用,但首先描述完整格式的声明并且显示各种
字段如何被缺省也很容易。

composed_of :attr_name,
:class_name => SomeClass,
:mapping => mapping

attr_name 参数指定将要给到“模型”类内的合成属性的名字。如果我们定义我们的
customer 为
class Customer < ActiveRecord::Base
composed_of :name, ...
end

我们就可以使用customer 对象的name 属性来访问合成对象。
customer = Customer.find(123)
puts customer.name.first

:class_name 选项用于指定持有合成数据的类的名字。选项的值可以是个类常量,或者
是包含类名字的字符串或符号。在我们例子,类是Name,所以我们可以指定
class Customer < ActiveRecord::Base
composed_of :name, :class_name => Name, ...
end
如果类名字是简单的属性名字的大小写混合形式,它可以被忽略。

:mapping 参数告诉“活动记录”表内列如何映射到合成对象内的属性和构造函数的参数
的。传递给:mapping 的参数即可以是一个有两个元素的数组,也可以是两个元素数组的一个数组。第二个元素是相应于合成属性内的存取器的名字。出现在映射参数定义内的元素的次
序,由那个数据库内被做为参数传递给合成对象的initialize()方法的列内容的次序决定。
图15.2 显示了映射是如何工作的。如果这个选项被忽略,“活动记录”假设数据库的列和合
成对象属性两者与“模型”属性有同样名字。
对于我们Name 类,我们需要映射三个数据库的列到合成对象内。customers 表定义是这
样。
create table customers (
id int not null auto_increment,
created_at datetime not null,
credit_limit decimal(10,2) default 100.0,
first_name varchar(50),
initials varchar(20),
last_name varchar(50),
last_purchase datetime,
purchase_count int default 0,
primary key (id)
);

列first_name, initials, 和last_name 应该在Name 类中被映射为first,
initials, 和last 属性。[在真实的应用程序中,我们更愿意让属性的名字与列的名字一样。
此处使用不同的名字是帮助我们显示参数是如何被映射的。]要把这个指定给“活动记录”,
我们使用下面声明。
class Customer < ActiveRecord::Base
composed_of :name,
:class_name => Name,
:mapping =>
[ # database ruby
[ :first_name, :first ],
[ :initials, :initials ],
[ :last_name, :last ]
]
end
尽管我们花了很多时间描述选项,但事实上它对创建这些映射的影响很小。一旦我们完
成了,就可以很容易地使用它们:“模型”对象内的合成属性将是你定义的合成类的一个实
例。
name = Name.new("Dwight", "D", "Eisenhower")
Customer.create(:credit_limit => 1000, :name => name)
customer = Customer.find(:first)
puts customer.name.first #=> Dwight
puts customer.name.last #=> Eisenhower
puts customer.name.to_s #=> Dwight D Eisenhower
customer.name = Name.new("Harry", nil, "Truman")
这个代码在customers 表内,用由新Name 对象内的属性firt,initials,和last 初始化
的列first_name,initials,和last_name 列创建了一个新行。它从数据库获得此行数据并通过合成对象来访问这些字段。注意你不能在合成对象内修改这些字段。相反你必须将它们传递给一个新对象。
合成对象并不是必须要映射数据库内的多个列到一个单独的对象内;它在用于接受一个
单独列并映射它为不是integer,float,string,或date 和time 的其它类型时是很有用处
的。通常的例子是表示货币的一个数据库列:不能持有负的浮点数据,你可能想创建特定的
Money 对象,它带有你应用程序需要的属性(如四舍五入为)。
回到196 页,我们看看我们是如何使用序列化声明来在数据库内存储结构化数据的。我
们也可以使用composed_of 声明来做到这些。做为对使用YAML 来序列化数据到数据库的列中的代替,我们使用一个合成对象来完成它自己序列化。做为一个例子,让我们再看看通过一
个customer 来存储最后五位购买者序列化的例子。先前,我们持有使用Ruby 数组的列表,并初始化它为一个YAML 字符串后再存入数据库。现在让我们包装信息到一个对象中,并且这个对象以它自己的格式存储数据。在这个例子中,我们将保存产品列表为一个用逗号分隔值的正常字符串。
首先,我们创建类LastFive 来包装列表。因为数据库在一个简单的字符串内存储列表,
所以它的构造函数将也接受字符串,并且我们需要一个能在字符串内返回内容的属性。尽管
在内部我们以Ruby 数组来存储列表。
class LastFive
attr_reader :list
# 接受包含"a,b,c" 样的字符串并存储成[ 'a', 'b', 'c' ]
def initialize(list_as_string)
@list = list_as_string.split(/,/)
end
# 返回我们的内容在以逗号分隔形式的字符串中。
def last_five
@list.join(',')
end
end
我们可以声明我们的LastFive 类包装了数据库内的last_five 列。
class Purchase < ActiveRecord::Base
composed_of :last_five
end
在我们运行它时,我们可以看到last_five 属性包含一个值的数组。
Purchase.create(:last_five => LastFive.new("3,4,5"))
purchase = Purchase.find(:first)
puts purchase.last_five.list[1] #=> 4
分享到:
评论

相关推荐

    华三交换机配置端口聚合之三层端口配置静态和动态聚合

    最后,使用命令display link-aggregation verbose查看聚合组信息。 二、配置三层端口动态聚合 在华三交换机上,配置三层端口动态聚合需要按照以下步骤进行: 首先,创建端口三层聚合口,并分配IP地址。例如,创建...

    MongoDB 聚合管道(Aggregation Pipeline)

    其中,聚合管道(Aggregation Pipeline)是MongoDB中一个非常重要的特性,用于对数据进行复杂处理和分析。接下来,我们将详细地探讨MongoDB聚合管道的相关知识点。 首先,从概念上理解,MongoDB的聚合管道可以类比...

    [面试/笔试系列6]关联、聚合(Aggregation)以及组合(Composition)的区别

    ### 关联、聚合(Aggregation)以及组合(Composition)的区别 在面向对象设计中,类之间的关系是非常重要的概念。这不仅有助于理解系统架构,还能帮助开发者更好地组织代码。本篇文章将详细探讨关联、聚合...

    H3C交换机链路聚合

    [R111-Route-Aggregation1]ip add 192.168.254.1 24 配置IP地址 三层聚合可直接配置 [R111]int range GigabitEthernet 6/1 GigabitEthernet 6/0 进入需要添加的端口 [R111-if-range]port link-aggregation group 3 ...

    Association, Aggregation and Composition的区别

    Aggregation(聚合) 聚合是一种特殊的关联,代表两个类之间的整体/局部关系。在聚合关系中,整体在概念上处于比局部更高的一个级别。聚合可以转换成 Java 中的一个实例作用域变量。聚合与关联的区别在于,聚合暗示...

    MongoDB的聚合框架Aggregation Framework入门学习教程

    MongoDB的聚合框架(Aggregation Framework)是数据库处理数据计算的核心工具,它允许开发者对数据进行复杂的分析和转换,以满足报告、统计和其他数据分析的需求。本教程将详细介绍MongoDB聚合框架的基本概念和常用...

    MA5680T链路聚合

    链路聚合(Link Aggregation)是一种将多个物理接口捆绑在一起作为一个逻辑接口的技术,旨在提高链路带宽、实现链路冗余。在企业级网络设备如华为MA5680T、MA5683T及MA5608T等OLT(Optical Line Terminal)设备中,...

    aggregation and disaggregation techniques and methodology in optimization

    在IT领域,尤其是在优化模型的研究与应用中,聚合(Aggregation)与解聚合(Disaggregation)技术及其方法论扮演着至关重要的角色。这些技术旨在处理数据与决策模型之间的复杂关系,平衡模型的细节程度与解决模型的...

    mongodb aggregation运用例子

    ### 聚合管道(Aggregation Pipeline) 聚合管道是一个多层次的处理过程,它将数据文档转换为聚合结果。它由多个阶段组成,每个阶段都按照声明的顺序进行操作。聚合管道中常见的一些操作包括: - **$match**: 过滤...

    cisco链路聚合实验

    Cisco设备支持多种链路聚合协议,包括LACP(Link Aggregation Control Protocol)和PAgP(Port Aggregation Protocol)。 在本文档中,我们将详细介绍如何使用Cisco设备进行链路聚合实验,包括二层交换和三层交换...

    aggregation:基类和混合类的聚合

    聚合 基类和混合类的聚合 关于 Aggregation 是一个非常小的 Node.js 环境的 JavaScript 库,只提供一个函数,用于基于 mixins 的 ECMAScript 5/6 类继承。 它将一个基类和一个或多个 mixin 类聚合为一个聚合类,然后...

    交换机链路聚合配置PPT课件.pptx

    在交换机链路聚合配置中,用户可以使用link-aggregation group命令创建相应的聚合组,并把需要聚合的端口加入到所创建的聚合组中,符合聚合条件的端口即可共同分担聚合链路的负荷。而对于动态汇聚方式,只需在端口...

    Django Aggregation聚合使用方法解析

    Djngo聚合就能满足这些要求。 以下面的Model为例 from django.db import models class Author(models.Model): name = models.CharField(max_length=100) age = models.IntegerField() class Publisher(models....

    以太网链路聚合技术 LACP 配置

    链路聚合的相关协议架构是在 IEEE 802.3 架构中,链路聚合功能是数据链路层的一个子功能,通过链路聚合子层(Link Aggregation Sublayer)实现。在 OSI 七层模型中,链路聚合子层的位置是在数据链路层和物理层之间。...

    tcp.tar.gz_aggregation_aggregation in ns2_ns2_ns2 aggregation_tc

    标题"tcp.tar.gz_aggregation_aggregation in ns2_ns2_ns2 aggregation_tc"暗示了我们即将探讨的是NS2中TCP协议与802.11 MAC层的聚合(aggregation)功能,以及可能涉及的TCP分片重组(fragment retransmission)...

    GXT组件使用教程4——Aggregation Grid

    Aggregation Grid是GXT中一个非常重要的特性,允许用户在网格中对数据进行聚合计算,例如求和、平均值、最大值等。 1. **GXT组件介绍** GXT组件包括表格、表单、菜单、工具栏、树形视图等,它们都具有高度可定制性...

    H3C_链路聚合基础配置案例

    - 建立名为Bridge-Aggregation1的链路聚合组,并将G1/0/47和G1/0/48端口加入到聚合组中。 - 配置聚合组的类型为TRUNK,允许所有VLAN的数据通过。 在SWB上,同样创建VLAN10和VLAN20,并将G1/0/1分配给VLAN10,G1...

    h3c链路聚合

    可以通过 display link-aggregation summary 命令来查看 Device A 上所有聚合组的摘要信息。 链路聚合的应用场景包括: * 数据中心的网络架构:链路聚合可以应用于数据中心的网络架构中,以提高网络的可靠性和带宽...

    elasticsearch聚合值过滤

    桶型聚合将数据分组到不同的桶中,如术语聚合(Term Aggregation)用于按字段分组,范围聚合(Range Aggregation)用于按数值范围分组;而指标型聚合则计算每个桶或整个搜索结果的单一值,如平均值(Avg)、总和...

Global site tag (gtag.js) - Google Analytics