在我的数据存储中,我有一个实体Book
,该实体引用了Owner
该实体,该实体引用了该实体ContactInfo
的属性zipcode
。我想查询某个邮政编码内的所有书籍。我怎样才能做到这一点?我知道我无法编写可以执行的查询:
q = db.Query(Book).filter('owner.contact_info.zipcode =', 12345)
在我的数据存储中,我有一个实体Book
,该实体引用了Owner
该实体,该实体引用了该实体ContactInfo
的属性zipcode
。我想查询某个邮政编码内的所有书籍。我怎样才能做到这一点?我知道我无法编写可以执行的查询:
q = db.Query(Book).filter('owner.contact_info.zipcode =', 12345)
这正是App Engine 数据存储区无法做到的事情。它不是一个关系数据库,你不能将它作为一个数据库来查询。这意味着其中一件事是它不支持 JOIN,并且您不能跨实体类型进行查询。
因此,在创建数据模型时遵循完整的规范化形式通常不是一个好主意。除非您有充分的理由将它们分开,否则 ContactInfo 几乎肯定应该与 Owner 合并。您可能还想在 Owner 上定义一个重复的 ReferenceProperty 记录books_owned
:然后您可以进行一个简单的查询,并且可以获取所有书籍:
owners = db.Query(Owner).filter('zipcode', 12345)
books = []
for owner in owners:
book_ids.extend(owner.books_owned)
books = db.get(book_ids)
编辑该字段将如下所示:
class Owner(db.Model):
...
books_owned = db.ListProperty(db.Key)
如果您更新架构,现有实体不会发生任何事情:您将需要遍历它们(可能使用远程 API)并更新它们以添加新数据。请注意,尽管您可以直接设置属性,但无需进行数据库迁移。
如果联系信息是一个单独的模型,您首先需要找到所有ContactInfo
带有的实体,zipcode == 12345
然后找到所有Owner
引用这些ContactInfo
实体的实体,然后找到所有Book
引用这些实体的Owner
实体。
如果您仍然能够更改模型定义,那么至少ContactInfo
在Owner
模型中进行非规范化可能是明智之举,也可能Owner
在每个Book
.