Правильный способ связывания нескольких значений с одним ключом состоит в том, чтобы упаковать список или значение словаря, используя, например, «json.dumps».
Вот Exemple:
#!/usr/bin/python
from json import dumps
from json import loads
import bsddb
# write
users = bsddb.hashopen("users.db","w")
primarykey = 'amz'
users[primarykey] = dumps(dict(username="amz", age=30, bio="craftsman"))
users.close()
# read
users = bsddb.hashopen("users.db","r")
for key in users.keys():
print loads(users[key])
users.close()
Это основной шаблон для использования с bsddb и применимо к другим DBS ключ/значение, как LevelDB.
Extra:
Учитывая тот факт, что ключи bsddb Hashmap упорядочены лексикографически (т.е. как питон 2 строки.), Вы можете построить HashMaps с ключами, имеющими predicatable порядка избавляя Вас идти через весь стол ,
Чтобы использовать эту функцию, вам необходимо создать полезные ключи. Снова вам понадобится функция упаковки, которая переводит порядок сортировки python в лексиграфический порядок (то есть 11 > 2
, но "11" < "2"
). Вот Exemple такая упаковка функция:
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))
Это своего рода наивные, вы можете пройти лишнюю милю и поддержку float
и лучший пакет int
для экономии места.
Например, при упрощенной схеме User(username, age)
вы можете построить еще один HashMap мы называем age_index
, с которой вы можете легко восстановить каждый пользователь в возрасте до 30 лет HashMap может выглядеть следующим образом:
key | value
-----------------
29 tom | X
30 amz | X
30 joe | X
30 moh | X
Этот представляет собой читаемый человеком вид hasmap: ключ фактически заполнен функцией pack
. Как вы можете видеть, клавиша составage
и primarykey
предмета, сохраненного ранее. В этом случае значение не используется, потому что оно нам не нужно. Имейте в виду, что каждый ключ является и должен быть уникальным.
После того, как эта схема на месте, вы делаете «выбор запросов», называемых запросами диапазона в bsddb, используя Cursor.set_range(key)
. Это установит курсор на ближайшую клавишу и вернет связанную пару ключ/значение (семантика может быть немного различной в зависимости от базы данных).
Например, получающим первое лицо, которое имеет age=30
, один можно использовать следующий код:
def get_first_person_with_age_thirty()
key, _ = age_index.set_range(pack(30)) # we don't need value
age, pk = unpack(key)
# set_range, will set the key to "30" and a pk
# or with a key prefix superior to 30.
# So we need to check that age is really 30.
if age == 30:
return loads(users[pk])
Это возвращает документ, связанный с пользователем amz
.
идти дальше нужно использовать другой интерфейс bsddb который точка входа bsddb.db.DB
и bsddb.db.DBEnv
(documentation]. С помощью этого интерфейса вы можете иметь несколько HashMap связанного с тем же контекстом транзакции, даже если это не требуется использовать транзакции ,
Избегайте использования модуля ['bsddb'] (http://docs.python.org/2/library/bsddb.html), поскольку он устарел. Если вы хотите, чтобы интерфейс типа «dict» был в БД, используйте модуль ['shelve'] (http://docs.python.org/2/library/shelve.html). Кроме того: если вы хотите сохранить больше одного объекта в качестве значения, используйте значение «list» как «и», а «добавьте» значения при их вставке. – Bakuriu
Могу ли я иметь больше объектов записей, хранящихся в db? – Jeremy
Что такое объект записи? Вы никогда не определяли его. Кроме того, что вы подразумеваете под «db»? Вы имеете в виду базу данных, обработанную 'shelve'? База данных в целом? – Bakuriu