大数据 爬虫Python AI Sql

05.实体关系

2020-05-09  本文已影响0人  gthank

05.实体关系

实体之间可以相互关联,两个实体之间的关系是由两个属性来定义的,这两个属性指定了关系的两端:

class Customer(db.Entity):
    orders = Set('Order')

class Order(db.Entity):
    customer = Required(Customer)

在上面的例子中,我们有两个关系属性:orderscustomer,当我们定义实体Customer时,实体Order还没有定义,这就是为什么我们要在订单属性中的订单周围加上引号。

另一种方法是使用lambda:

class Customer(db.Entity):
    orders = Set(lambda: Order)

如果你想让你的IDE检查声明的实体名称并高亮显示错别字,这可能很有用。

一些映射器 (例如 Django) 只要求在一侧定义关系,Pony 要求在两边显式地定义关系 (正如《Python之禅》中所说:显式比隐式更好),这使得用户可以从每个实体的角度看所有的关系。

所有的关系都是双向的。如果你更新了一个关系的一边,另一边也会自动更新。例如,如果我们创建了一个订单实体Order的实例,客户的订单集将被更新至包含这个新订单。

关系有三种类型:一对一、一对多和多对多关系。一对一的关系很少使用,大多数实体之间的关系是一对多和多对多的关系。

如果两个实体之间有一对一的关系,那往往意味着它们可以组合成一个实体。

如果你的数据图有很多一对一的关系,那么这可能是你需要重新考虑实体定义的信号。

个人意见:这个需要根据实际需求来定,如果一个表很宽(字段很多),这时候可以根据业务及使用频率,考虑将其拆分为多个表——gthank

一对多的关系

下面是一个单对多关系的例子:

class Order(db.Entity):
    items = Set("OrderItem")

class OrderItem(db.Entity):
    order = Required(Order)

在上面的例子中,没有订单,OrderItem的实例就不能存在。如果我们想让OrderItem的实例不被分配给一个订单而存在,我们可以将订单属性定义为Optional:

class Order(db.Entity):
    items = Set("OrderItem")

class OrderItem(db.Entity):
    order = Optional(Order)

多对多的关系

为了创建多对多关系,你需要将关系的两端定义为Set属性。

class Product(db.Entity):
    tags = Set("Tag")

class Tag(db.Entity):
    products = Set(Product)

为了在数据库中实现这种关系,Pony将创建一个中间表。这是一个众所周知的解决方案,可以让你在关系型数据库中拥有多对多关系。

一对一关系

为了创建一对一的关系,应该将关系属性定义为Optional-RequiredOptional-Optional

class Person(db.Entity):
    passport = Optional("Passport")

class Passport(db.Entity):
    person = Required("Person")

不允许将这两个属性定义为必填,因为这样做没有意义。

自我引用

一个实体可以使用自我参照关系与自身建立关系。这种关系可以分为两种类型:对称关系和非对称关系。

非对称关系是由属于同一实体的两个属性定义的。

对称关系的具体情况是,实体只指定了一个关系属性,而这个属性定义了关系的双方。这种关系可以是一对一的关系,也可以是多对多的关系。下面是自引用关系的例子。

class Person(db.Entity):
    name = Required(str)
    spouse = Optional("Person", reverse="spouse") # 对称的一对一
    friends = Set("Person", reverse="friends")    # 对称的多对多
    manager = Optional("Person", reverse="employees") # 非对称的一面
    employees = Set("Person", reverse="manager") # 非对称的另一面

两个实体之间的多重关系

当两个实体之间有一个以上的关系时,Pony需要指定反向属性,这样做的目的是为了让Pony知道哪一对属性之间有关系。

让我们考虑一下这个数据图,在这个数据图中,用户可以写推文,也可以收藏推文:

class User(db.Entity):
    tweets = Set("Tweet", reverse="author")
    favorites = Set("Tweet", reverse="favorited")

class Tweet(db.Entity):
    author = Required(User, reverse="tweets")
    favorited = Set(User, reverse="favorites")

在上面的例子中,我们必须指定反向选项。如果你试图为实体定义生成映射而不指定反向属性,你会得到异常pony.orm.core.erDiagramError: "Ambiguous reverse attribute for Tweet.author"

之所以出现这种情况,是因为属性author在技术上可以与tweetsfavorites相关,而Pony没有任何信息说明应该使用哪个属性。

上一篇 下一篇

猜你喜欢

热点阅读