jsonDB是一個基於JSON格式的內存數據庫.它具備如下特色:python
- 輕量級. 無守護進程,無需任何額外的安裝和配置,你只須要
import jsonDb
便可使用,很是方便.- NOSQL. 相似於mongoDb的非關係型數據庫.
- 內存數據庫. 全部數據基於內存進行操做和訪問,性能相對較高.目前版本的性能測試數據請 參考reference文檔.
- 任意遷移. 數據庫能夠完整導出爲外部文件,而且能夠從外部文件導入.基於此,數據庫能夠 進行任意的遷移,而無需作任何修改.
- 靈活的數據類型. 一個數據集合(collection)中的數據,並不須要相同的格式.好比如下幾種數據 能夠同時存在於一個collection中:
{'key1':1},{'key2':'value','pic':'value'},{'key3':'value'}
JsonDB使用python語言實現,是一個github開源項目,遵循MIT的LICENCE,基本上能夠不受限制用於任何用途。git
該DB的接口大致模仿了mongoDB的風格,使用起來很是簡單和順手。github
- db: 即數據庫. 建立一個jsonDb類的實例,便是建立了一個數據庫.能夠指定dbname和hash的長度.
- collection: 數據集合(表). 一個collection能夠理解爲數據庫中的一個表. collection不須要 單首創建,當insert第一條數據,或者ensureKey時,系統會自動建立.
- data: 數據. collection中的一條數據,或者是一個數據的list. data必須是dict字典類型,是一個 key-value鍵值對.
如下關鍵詞屬於系統保留,不能做爲任何字典dict的key名.數據庫
$lt $lte $gt $gte $ne $or $or[0-9] $jdb $jdb_collections $jdb_key $jdb_hash $jdb_coll $jdb_hashSize $jdb_md5
python setup.py install
pip install jsonDb
不少操做會使用到Filter條件過濾器.好比,刪除數據\更新數據\查詢數據等.經過過濾器,咱們能夠指定更新一組知足必定條件的數據. jsonDb提供了相對豐富和靈活的過濾器. 過濾器通常在方法的參數中使用filter來指定.json
filter是一個dict,它包括key,value,邏輯表達式,條件表達式 幾個部分.性能
filter={'邏輯表達式':{key:{'條件表達式':value}}}
邏輯表達式: 支持兩種邏輯測試
'$or'
'$or1'
'$or2'
...,,若是存在多個邏輯或,須要使用$or[0-9],例如:filter={'$or':{'key1':value1, 'key2':value2,...}, '$or1':{'key1':value1, 'key2':value2,...}, ...}
filter={'key1':value1, 'key2':value2,...}
條件表達式: 條件表達式是用來表示key和value之間的關係操作系統
{<key>:<value>}
{<key>:{$lt:<value>}}
{<key>:{$lte:<value>}}
{<key>:{$gt:<value>}}
{<key>:{$gte:<value>}}
{<key>:{$ne:<value>}}
Filter支持任意嵌套,這樣使用起來會很是靈活.以下:debug
filter={'$or':{'key1':value1, '$or':{'key1':value1, '$or1':{'key1':value1, 'key2':value2,...},...},...}, '$or1':{'key1':value1, 'key2':value2,...}, ...}
實例化一個JSONDB類實例,即建立一個數據庫.咱們重載了__str__
方法,因此能夠經過print
直接查看數據庫的統計信息.調試
>>> from jsonDb.database import JSONDB >>> myDb = JSONDB('USER_DB') >>> print myDb ------ jdb statics ------ db_name: USER_DB mem_collection: 0 bytes mem_hash: 0 bytes collection_num: 0 **** collection statics ****
jsonDB是內存數據庫,一個數據庫本質上就是一個類實例.因此數據庫隨類實例進行刪除和釋放.你能夠經過del
方法刪除這個類實例, 固然也可讓python本身回收.
插入一條數據,則對應的collection自動建立.能夠插入一條或多條數據,必須經過list
格式組織.單條數據必須是dict
格式.
>>> myDb.insert('COL_CUSTOMERS',[{'id':1, 'name':'Jeffery', 'sex':'male', 'age':18, 'birth':'1990-01-03'}]) True >>> print myDb ------ jdb statics ------ db_name: USER_DB mem_collection: 104 bytes mem_hash: 0 bytes collection_num: 1 **** collection statics **** name: COL_CUSTOMERS data_num: 0 key: [] index: False data_mem: 104 bytes hash_mem: 0 bytes >>>
能夠經過find()
查看插入結果,爲了顯示格式更加便於閱讀,JSONDB提供了靜態格式化打印方法rprint()
:
>>> JSONDB.rprint(myDb.find('COL_CUSTOMERS'),indent=4) [ { "name": "Jeffery", "age": 18, "id": 1, "birth": "1990-01-03", "sex": "male" } ] >>>
也能夠同時插入多條數據
>>> dataList = [{'id':2, 'name':'Jack', 'sex':'male', 'age':29, 'birth':'1990-01-03'}, ... {'id':3, 'name':'Tom', 'age':18, 'birth':'1991-01-03'}, ... {'id':4, 'name':'Wang', 'sex':'male', 'age':40, 'job':'software engineer'}] >>> myDb.insert('COL_CUSTOMERS',dataList) True >>> JSONDB.rprint(myDb.find('COL_CUSTOMERS',filter={'id':{'$gte':2}}),indent=4) [ { "name": "Jack", "age": 29, "id": 2, "birth": "1990-01-03", "sex": "male" }, { "age": 18, "id": 3, "birth": "1991-01-03", "name": "Tom" }, { "id": 4, "job": "software engineer", "age": 40, "name": "Wang", "sex": "male" } ] >>>
上面使用了find()
方法的條件查詢,只查詢了'id'
大於等於2的數據.同時,每條data之間的格式不須要一致.
刪除一條指定的數據:
>>> JSONDB.rprint(myDb.find('COL_CUSTOMERS',filter={'id':1}),indent=4) [ { "name": "Jeffery", "age": 18, "id": 1, "birth": "1990-01-03", "sex": "male" } ] >>> myDb.delete('COL_CUSTOMERS',filter={'id':1}) True >>> JSONDB.rprint(myDb.find('COL_CUSTOMERS',filter={'id':1}),indent=4) [] >>>
一樣,咱們能夠經過filter過濾器來條件刪除多條數據,好比咱們要刪除全部'age'
大於10而且小於30的記錄:
>>> JSONDB.rprint(myDb.find('COL_CUSTOMERS'),indent=4) [ { "name": "Jack", "age": 29, "id": 2, "birth": "1990-01-03", "sex": "male" }, { "age": 18, "id": 3, "birth": "1991-01-03", "name": "Tom" }, { "id": 4, "job": "software engineer", "age": 40, "name": "Wang", "sex": "male" }, { "name": "Jeffery", "age": 18, "id": 1, "birth": "1990-01-03", "sex": "male" } ] >>> myDb.delete('COL_CUSTOMERS',filter={'age':{'$gt':10,'$lt':30}}) True >>> JSONDB.rprint(myDb.find('COL_CUSTOMERS'),indent=4) [ { "id": 4, "job": "software engineer", "age": 40, "name": "Wang", "sex": "male" } ] >>>
>>> JSONDB.rprint(myDb.find('COL_CUSTOMERS',filter={'name':'Wang'}),indent=4) [ { "id": 4, "job": "software engineer", "age": 40, "name": "Wang", "sex": "male" } ] >>> myDb.update('COL_CUSTOMERS',set={'job':'doctor'},filter={'name':'Wang'}) True >>> JSONDB.rprint(myDb.find('COL_CUSTOMERS',filter={'name':'Wang'}),indent=4) [ { "id": 4, "job": "doctor", "age": 40, "name": "Wang", "sex": "male" } ] >>>
數據查詢可使用Filter過濾器來實現豐富的查找功能.
>>> JSONDB.rprint(myDb.find('COL_CUSTOMERS'),indent=4) [ { "name": "Jeffery", "age": 18, "id": 1, "birth": "1990-01-03", "sex": "male" }, { "name": "Jack", "age": 29, "id": 2, "birth": "1990-01-03", "sex": "male" }, { "age": 18, "id": 3, "birth": "1991-01-03", "name": "Tom" }, { "id": 4, "job": "software engineer", "age": 40, "name": "Wang", "sex": "male" } ] >>> JSONDB.rprint(myDb.find('COL_CUSTOMERS',filter={'$or':{'age':{'$gt':20},'id':{'$gte':3}}}),indent=4) [ { "name": "Jack", "age": 29, "id": 2, "birth": "1990-01-03", "sex": "male" }, { "age": 18, "id": 3, "birth": "1991-01-03", "name": "Tom" }, { "id": 4, "job": "software engineer", "age": 40, "name": "Wang", "sex": "male" } ]
若是不指定collection,那麼將在整個數據庫中查找.目前暫不支持指定多個collection查找.
能夠經過limit
參數來限制返回數據的條數,默認爲0,也就是返回全部.以下:
>>> JSONDB.rprint(myDb.find('COL_CUSTOMERS',filter={'$or':{'age':{'$gt':20},'id':{'$gte':3}}},limit=2),indent=4) [ { "name": "Jack", "age": 29, "id": 2, "birth": "1990-01-03", "sex": "male" }, { "age": 18, "id": 3, "birth": "1991-01-03", "name": "Tom" } ]
目前版本暫不支持排序和指定返回字段集,後續版本會陸續支持.
能夠經過ensureKey()
給collection指定key值,這個key值是一個list,能夠是一個多元組key. 指定了key值的collection將會保證key值的惟一性,也就是說collection中的數據key值不會重複. 同時,指定了key值事後,將會爲該collection自動建立一個hash表,創建索引.在find()
中, 若是filter
是嚴格指定的key值,那麼將自動進行hash查找,查找效率比普通查找高不少.hash表 的大小在建立數據庫時能夠指定hashSize
,默認是1000. 須要注意的是,咱們只能當collection裏面沒有數據時才能調用ensureKey()
,一旦有插入數據後再指定Key值則失敗.
經過merge()
將一個數據庫合併到另一個數據庫裏面.合併中若是遇到數據衝突(好比key值衝突),則合併失敗.
>>> mergeDb = JSONDB('mergeDb') >>> mergeDb.insert('COL1',[{'id':1,'name':'Wang'}]) True >>> mergeToDb = JSONDB('mergeToDb') >>> mergeToDb.insert('COL1',[{'id':2,'name':'LI'}]) True >>> mergeToDb.insert('COL2',[{'idX':1,'nameX':'Lee'}]) True >>> mergeDb.merge(mergeToDb) True >>> JSONDB.rprint(mergeDb.find(),indent=4) [ { "id": 1, "name": "Wang" }, { "id": 2, "name": "LI" }, { "idX": 1, "nameX": "Lee" } ] >>>
jsonDB是內存數據庫,爲了數據的持久存儲,咱們支持將內存數據庫導出到外部磁盤文件中.
>>> mergeDb.exportToFile() True
默認將文件導出到./db/
目錄下,db文件以數據庫的名字命名. 上例中將導出到./db/mergeDb
.
導出的過程是比較耗時的,目前咱們不支持實時導出,須要使用者適配這部分功能.
支持從外部文件中導入數據到一個JSONDB類實例中.
>>> importDb = JSONDB('DB_IMPORT') >>> importDb.importFromFile(fileName='mergeDb') True
導入的數據庫文件,必須是經過exportToFile()
導出生成的,不然導入操做可能會失敗. 爲了防止外部文件數據被篡改,咱們使用了MD5
進行數據完整性校驗,因此不要修改導出的數據文件.
>>> myDb.debugSwitch(1)
參數indent
表示縮進的字符個數
>>> JSONDB.rprint(mergeDb.find(),indent=4) [ { "id": 1, "name": "Wang" }, { "idX": 1, "nameX": "Lee" } ]
使用print
方法便可打印出數據庫的詳細統計信息.
>>> print myDb ------ jdb statics ------ db_name: USER_DB mem_collection: 104 bytes mem_hash: 0 bytes collection_num: 1 **** collection statics **** name: COL_CUSTOMERS data_num: 0 key: [] index: False data_mem: 104 bytes hash_mem: 0 bytes >>>
方法perfDotStart()
和perfDotEnd()
配對使用,提供對關鍵流程的耗時統計,毫秒級.
myDb.perfDotStart() for i in range(1,1000): myDb.insert('COL_CUSTOMERS',[{'id':i, 'name':'Jeffery', 'sex':'male', 'age':18, 'birth':'1990-01-03'}]) myDb.find('COL_CUSTOMERS',filter={'id':500}) myDb.perfDotEnd()
輸出結果:
------ perf dot statics ------ [insert]spend time: 0.005295753479 [find]spend time: 0.014662027359
注意,這裏統計的是某個關鍵流程的總耗時.好比,期間進行了屢次insert()
操做,那麼insert的耗時統計是全部這些的總和.
jsonDb是基於內存存儲,因此總體性能足以知足一些小型的數據庫應用.
做者用來測試的PC性能:
mac air book 處理器 1.4 GHz Intel Core i5 內存 4 GB 1600 MHz DDR3 操做系統 OS X 10.9.5 (13F1603)
測試十萬條數據的插入\刪除\查詢操做:
from jsonDb.database import JSONDB myDb = JSONDB('USER_DB') myDb.perfDotStart() for i in range(0,100000): myDb.insert('COL_CUSTOMERS',[{'id':i, 'name':'Jeffery', 'sex':'male', 'age':18, 'birth':'1990-01-03'}]) myDb.perfDotEnd() myDb.perfDotStart() myDb.find('COL_CUSTOMERS',filter={'id':500}) myDb.perfDotEnd() myDb.perfDotStart() myDb.delete('COL_CUSTOMERS',filter={'id':10000}) myDb.perfDotEnd()
打點結果以下:
------ perf dot statics ------ [insert]spend time: 0.450565576553 ------ perf dot statics ------ [find]spend time: 1.62476110458 ------ perf dot statics ------ [find]spend time: 1.59516096115 [delete]spend time: 1.59673404694
指定了key值事後,會創建索引,因此會大大提升查找性能,可是插入性能會有必定降低.
from jsonDb.database import JSONDB myDb = JSONDB('USER_DB') # 指定key值 myDb.ensureKey('COL_CUSTOMERS',['id']) myDb.perfDotStart() for i in range(0,100000): myDb.insert('COL_CUSTOMERS',[{'id':i, 'name':'Jeffery', 'sex':'male', 'age':18, 'birth':'1990-01-03'}]) myDb.perfDotEnd() myDb.perfDotStart() myDb.find('COL_CUSTOMERS',filter={'id':500}) myDb.perfDotEnd() myDb.perfDotStart() myDb.delete('COL_CUSTOMERS',filter={'id':10000}) myDb.perfDotEnd()
打點結果以下:
------ perf dot statics ------ [insert]spend time: 6.04253554344 ------ perf dot statics ------ [find]spend time: 9.91821289062e-05 ------ perf dot statics ------ [find]spend time: 6.50882720947e-05 [delete]spend time: 0.00128698348999
遵循 The MIT License (MIT),你能夠不受約束地使用該項目代碼和生成件.
mail:hujiang001@gmail.com https://github.com/hujiang001/jsonDB