回答
你必須選擇一個「列」爲重點(必須是唯一的,我想這將是你的情況「用戶名」) - 的唯一途徑搜索將永遠不可能發生。其他列可以用任何你喜歡的方式作爲該鍵的單個字符串值,從酸洗到簡單連接一個保證在任何列中都不會出現的字符,比如'\ 0' 「可讀的文本字符串」。
如果您需要能夠通過不同的鍵進行搜索,則需要將其他輔助和單獨的bsddb數據庫設置爲主表中的「索引」 - 這有很多工作要做,並且有大量關於學科。 (或者,你可以轉向更高層次的抽象技術,比如sqlite,它可以代表你整潔地處理索引;-)。
tl,dr:要在berkley db這樣的有序鍵值存儲區中表示多個列,您需要了解關鍵構成。查看關於bsddb的其他答案以瞭解更多信息。
有幾種方法可以做到,使用命令鍵/值存儲。
最簡單的解決方法是store documents as json values with a correct key。
現在你可能要建立在這些列檢索文件的索引,而不必遍歷所有的HashMap來找到正確的對象。爲此,您可以使用secondaryDB,它會自動爲您建立索引。或者你可以自己建立索引。
如果你不想處理key packing(這是一個好主意,開始了),你可以利用DB.set_bt_compare,這將允許同時還具有您使用的cPickle,JSON或msgpack兩個鍵和值這個命令可以用來創建索引並進行查詢。這是較慢的方法,但引入關鍵組合的模式。
要充分利用什麼下令關鍵是,你可以利用Cursor.set_range(key)
設置數據庫的位置在查詢的開始。
另一種模式,被稱爲EAV模式商店後面的方案(entity, attribute, value)
元組,然後你通過使用元組的排列訂做各種指標。我學習了這種模式研究數據組。對於較少資源的飢餓數據庫,您將採用「靜態類型」方式,並儘可能多地將常見信息存儲在「元數據」表中,並將文檔(實際上是RDBMS表)分割成它們自己的散列表。
爲了讓您在這裏開始使用bsddb的示例數據庫(但您可以使用其他有序的鍵/值存儲如wiredtiger或leveldb構建它)來實現EAV模式。在這個實現中,我將EAV交換爲IKV,它轉換爲唯一標識符,密鑰,值。總體結果是,你有一個完全索引模式少文檔數據庫。我認爲這是效率和易用性之間的妥協。
import struct
from json import dumps
from json import loads
from bsddb3.db import DB
from bsddb3.db import DBEnv
from bsddb3.db import DB_BTREE
from bsddb3.db import DB_CREATE
from bsddb3.db import DB_INIT_MPOOL
from bsddb3.db import DB_LOG_AUTO_REMOVE
def pack(*values):
def __pack(value):
if type(value) is int:
return '1' + struct.pack('>q', value)
elif type(value) is str:
return '2' + struct.pack('>q', len(value)) + value
else:
data = dumps(value, encoding='utf-8')
return '3' + struct.pack('>q', len(data)) + data
return ''.join(map(__pack, values))
def unpack(packed):
kind = packed[0]
if kind == '1':
value = struct.unpack('>q', packed[1:9])[0]
packed = packed[9:]
elif kind == '2':
size = struct.unpack('>q', packed[1:9])[0]
value = packed[9:9+size]
packed = packed[size+9:]
else:
size = struct.unpack('>q', packed[1:9])[0]
value = loads(packed[9:9+size])
packed = packed[size+9:]
if packed:
values = unpack(packed)
values.insert(0, value)
else:
values = [value]
return values
class TupleSpace(object):
"""Generic database"""
def __init__(self, path):
self.env = DBEnv()
self.env.set_cache_max(10, 0)
self.env.set_cachesize(5, 0)
flags = (
DB_CREATE |
DB_INIT_MPOOL
)
self.env.log_set_config(DB_LOG_AUTO_REMOVE, True)
self.env.set_lg_max(1024 ** 3)
self.env.open(
path,
flags,
0
)
# create vertices and edges k/v stores
def new_store(name):
flags = DB_CREATE
elements = DB(self.env)
elements.open(
name,
None,
DB_BTREE,
flags,
0,
)
return elements
self.tuples = new_store('tuples')
self.index = new_store('index')
self.txn = None
def get(self, uid):
cursor = self.tuples.cursor()
def __get():
record = cursor.set_range(pack(uid, ''))
if not record:
return
key, value = record
while True:
other, key = unpack(key)
if other == uid:
value = unpack(value)[0]
yield key, value
record = cursor.next()
if record:
key, value = record
continue
else:
break
else:
break
tuples = dict(__get())
cursor.close()
return tuples
def add(self, uid, **properties):
for key, value in properties.items():
self.tuples.put(pack(uid, key), pack(value))
self.index.put(pack(key, value, uid), '')
def delete(self, uid):
# delete item from main table and index
cursor = self.tuples.cursor()
index = self.index.cursor()
record = cursor.set_range(pack(uid, ''))
if record:
key, value = record
else:
cursor.close()
raise Exception('not found')
while True:
other, key = unpack(key)
if other == uid:
# remove tuple from main index
cursor.delete()
# remove it from index
value = unpack(value)[0]
index.set(pack(key, value, uid))
index.delete()
# continue
record = cursor.next()
if record:
key, value = record
continue
else:
break
else:
break
cursor.close()
def update(self, uid, **properties):
self.delete(uid)
self.add(uid, **properties)
def close(self):
self.index.close()
self.tuples.close()
self.env.close()
def debug(self):
for key, value in self.tuples.items():
uid, key = unpack(key)
value = unpack(value)[0]
print(uid, key, value)
def query(self, key, value=''):
"""return `(key, value, uid)` tuples that where
`key` and `value` are expressed in the arguments"""
cursor = self.index.cursor()
match = (key, value) if value else (key,)
record = cursor.set_range(pack(key, value))
if not record:
cursor.close()
return
while True:
key, _ = record
other = unpack(key)
ok = reduce(
lambda previous, x: (cmp(*x) == 0) and previous,
zip(match, other),
True
)
if ok:
yield other
record = cursor.next()
if not record:
break
else:
break
cursor.close()
db = TupleSpace('tmp')
# you can use a tuple to store a counter
db.add(0, counter=0)
# And then have a procedure doing the required work
# to alaways have a fresh uid
def make_uid():
counter = db.get(0)
counter['counter'] += 1
return counter['counter']
amirouche = make_uid()
db.add(amirouche, username="amirouche", age=30)
print(db.get(amirouche))
- 1. Python Berkeley DB/Sqlite
- 2. autonicrement berkeley db,或者列表
- 3. 在Berkeley DB的
- 4. berkeley db java中的多個鍵
- 5. 的Berkeley DB,併發隊列
- 6. Berkeley DB的GUI
- 7. Berkeley DB for iPhone
- 8. Berkeley DB的最佳Python模塊?
- 9. GAE上的berkeley DB
- 10. Heroku上的Berkeley DB
- 11. 可以在手機中使用Berkeley DB
- 12. DEADLOCK_WRAP在python中使用Berkeley DB時出錯(bsddb)
- 13. 使用Berkeley DB(bsddb模塊),Python
- 14. Berkeley DB Core和Berkeley DB之間的選擇JE
- 15. Berkeley DB中的交易。快速?
- 16. Berkeley DB中的空間索引
- 17. Berkeley DB中的突變錯誤
- 18. Oracle Berkeley DB Java版中的重複鍵
- 19. Berkeley XML DB「where」analog
- 20. Berkeley DB SIGBUS錯誤
- 21. 我可以在Berkeley DB中使用多個密鑰嗎?
- 22. 的SQLite,Berkeley DB的標杆
- 23. Berkeley DB和C++的問題
- 24. Berkeley DB的用法如何?
- 25. Berkeley DB的平臺遷移
- 26. Berkeley DB中的多線程應用程序
- 27. 從berkeley db中刪除主索引
- 28. 在java中檢索Berkeley DB中的所有記錄
- 29. 如何將多個文檔放入Berkeley-DB XML容器中?
- 30. 如何查看Berkeley DB(Perl)中有多少個密鑰?
你看我的回答https://stackoverflow.com/a/32148388/140837 – amirouche 2017-09-19 16:48:53