虽然您可以将整个数据结构存储在单个 HDF5 表中,但将所描述的类存储为三个单独的变量可能要容易得多 - 两个 1D 整数数组和一个用于存储“照片”属性的数据结构。
如果您关心文件大小和速度而不关心文件的人类可读性,您可以将 64 个布尔值建模为 UINT8 的 8 个 1D 数组或 UINT8 的 2D 数组 N x 8(或 CHAR) .然后,您可以实现一个简单的接口,将您的布尔值打包成 UINT8 位并返回(例如,How to convert a boolean array to an int array)
据了解,HDF5 中没有内置搜索功能,但您可以读取包含 user_ids 的变量,然后简单地使用 Python 查找与您的 user_id 匹配的所有元素的索引。
获得索引后,您可以读取其他变量的相关切片。 HDF5 原生支持高效切片,但它适用于范围,因此您可能想考虑如何将具有相同 user_id 的记录存储在连续的块中,请参阅此处的讨论
h5py: Correct way to slice array datasets
您可能还想研究 pytables - 一种基于 hdf5 构建的 Python 接口,用于将数据存储在类似表的结构中。
import numpy as np
import h5py
class C:
def __init__(self, id, user_id, photo):
self.id = id
self.user_id = user_id
self.photo = photo
def write_records(records, file_out):
f = h5py.File(file_out, "w")
dset_id = f.create_dataset("id", (1000000,), dtype='i')
dset_user_id = f.create_dataset("user_id", (1000000,), dtype='i')
dset_photo = f.create_dataset("photo", (1000000,8), dtype='u8')
dset_id[0:len(records)] = [r.id for r in records]
dset_user_id[0:len(records)] = [r.user_id for r in records]
dset_photo[0:len(records)] = [np.packbits(np.array(r.photo, dtype='bool').astype(int)) for r in records]
f.close()
def read_records_by_id(file_in, record_id):
f = h5py.File(file_in, "r")
dset_id = f["id"]
data = dset_id[0:2]
res = []
for idx in np.where(data == record_id)[0]:
record = C(f["id"][idx:idx+1][0], f["user_id"][idx:idx+1][0], np.unpackbits( np.array(f["photo"][idx:idx+1][0], dtype='uint8') ).astype(bool))
res.append(record)
return res
m = [ True, False, True, True, False, True, True, True]
m = m+m+m+m+m+m+m+m
records = [C(1, 3, m), C(34, 53, m)]
# Write records to file
write_records(records, "mytestfile.h5")
# Read record from file
res = read_records_by_id("mytestfile.h5", 34)
print res[0].id
print res[0].user_id
print res[0].photo