ORM:Object Relational Mapping。比較著名的有Django的ORM,SQLAlchemy。
ODM:Object Document Mapping,本質(zhì)也屬于一種ORM,不過是基于MongoDB、Redis這種NoSQL的。這個詞我感覺并不是業(yè)界通用的,首先在搜索引擎上,這個詞沒什么相關(guān)的結(jié)果;其次,MongoDB可以講Document,但是Redis就不合適了。我用過的有MongoDB的MongoEngine,Redis的Walrus。雖然這個詞某種意義上不準確,但下文為了方便還是使用它。
使用原生的NoSQL命令有時候很繁瑣,我們總會不自覺地對它們進行封裝。如果我們想要將一個ORM的對象及相關(guān)的一些方法運算結(jié)果保存在NoSQL中,如果可以通過類似ORM的操作,而不是逐個地去保存、獲取,是不是會方便一些?
需要構(gòu)造的框架具體關(guān)系如圖。DataModel指的是ORM中的Model,CacheModel指的是ODM的Model,二者通過Binding來連接。
在DataModel和CacheModel中,定義Model和我們通常的做法完全一樣。
在Binding中,除去定義是哪兩個Model進行關(guān)聯(lián)外,最主要是要定義一個字典field_mapping,用來將兩個Model中的字段、方法一一對應(yīng)。
class Article(DataModel):
id = IntegerField()
title = CharField()
description = TextField()
create_date = DateField()
image = ImageField()
votes = Many2manyField('user')
def get_vote_list(self):
return [(user.id, user.name) for user in votes]
class ArticleCache(CacheModel):
id = IntegerField()
title = CharField()
description = TextField()
create_date = DateField()
image = CharField()
vote_list = ListField()
class ArticleBinding(Binding):
data_model = Article
cache_model = ArticleCache
field_mapping = {
'id': 'id',
'title': 'title',
'description': 'description',
'create_date': 'create_date',
'image': 'image.url',
'vote_list': '.get_vote_list',
}
大體上的定義方法如上所示,應(yīng)該說比較清晰的。
在具體去取數(shù)據(jù)時,需要DataModel提供一個方法,來獲取到對應(yīng)的CacheModel,這當然是需要通過Binding的。
以上是對使用者而言,對框架創(chuàng)建者,除了要提供以上所述的這些內(nèi)容外,最主要的是:
- 設(shè)計字段轉(zhuǎn)換方法,因為就算DataModel和CacheModel中都是DateField,但里面保存的內(nèi)容很可能是不同的。特別是很多ORM里面都有一些獨有的字段。對于One2Many,Many2One,Many2Many字段則不能直接轉(zhuǎn)換。
- 設(shè)計手動/自動更新機制,使用ODM肯定是需要要做好數(shù)據(jù)一致性,如果某些數(shù)據(jù)實時性比較強,經(jīng)常在變,那建議最好不要使用這種緩存框架,除非設(shè)計好符合業(yè)務(wù)場景的緩存刷新機制。一般而言,保存到ODM中的數(shù)據(jù)能夠保持一定時間不需要變化,這樣比較簡單。
- 設(shè)計過期機制。這個和第2點是相關(guān)的。
其實這樣搞下來,是有點臃腫的:一個模型對應(yīng)了兩個具體實現(xiàn),一般來講對應(yīng)一個也就夠了。所以這種框架的應(yīng)用場景估計也不會太廣吧。。。