単一のリストから始めましょう。単一のハッシュマップで作業できます。
0
ユーザーの注文数を行に保存する
- 新しい注文ごとに、カウントがインクリメントされた新しい行を保存します
したがって、夜ハッシュマップは次のようになります。
key | value
-------------
0 | 5
1 | tomato
2 | celery
3 | apple
4 | pie
5 | meat
キーの着実なインクリメントにより、すべてのキーが一意であることを確認します。データベースがキー順であり、 pack 関数が整数を正しく順序付けられたバイト配列のセットに変換するという事実を考えると、リストのスライスを取得できます。5000 から 5050 の間の注文を取得するには、bsddbCursor.set_range
または leveldb createReadStream
(js api)を使用できます。
次に、複数のユーザー注文に拡張しましょう。複数のハッシュマップを開くことができる場合は、複数のハッシュマップを使用して上記を使用できます。たぶん、いくつかのシステムの問題 (開いている fds の最大 nb またはディレクトリごとのファイルの最大数) に遭遇するでしょう。したがって、単一のハッシュマップを使用して、複数のユーザーで同じハッシュマップを共有できます。
pack
以下で説明することは、辞書式順序 (バイトオーダー) を使用して正しくキーを設定すると、leveldb と bsddb の両方で機能します。だから私はあなたが機能を持っていると仮定しますpack
。bsddb では、pack
自分で関数を作成する必要があります。インスピレーションを得るには、wiredtiger.packing
またはbytekeyをご覧ください。
原則は、ユーザーの ID を使用してキーの名前空間を作成することです。キーコンポジションとも呼ばれます。
データベースが次のようになっているとします。
key | value
-------------------
1 | 0 | 2 <--- count column for user 1
1 | 1 | tomato
1 | 2 | orange
... ...
32 | 0 | 1 <--- count column for user 32
32 | 1 | banna
... | ...
このデータベースは、次の (疑似) コードで作成します。
db.put(pack(1, make_uid(1)), 'tomato')
db.put(pack(1, make_uid(1)), 'orange')
...
db.put(pack(32, make_uid(32)), 'bannana')
make_uid
実装は次のようになります。
def make_uid(user_uid):
# retrieve the current count
counter_key = pack(user_uid, 0)
value = db.get(counter_key)
value += 1 # increment
# save new count
db.put(counter_key, value)
return value
次に、正しい範囲検索を行う必要があります。これは、単一の複合キーに似ています。bsddb apiを使用して、 userとのcursor.set_range(key)
間のすべてのアイテムを取得します。5000
5050
42
def user_orders_slice(user_id, start, end):
key, value = cursor.set_range(pack(user_id, start))
while True:
user_id, order_id = unpack(key)
if order_id > end:
break
else:
# the value is probably packed somehow...
yield value
key, value = cursor.next()
エラーチェックは行われません。とりわけuser_orders_slice(42, 5000, 5050)
、リストから項目を削除した場合、スライスによって 51 個の項目が引き裂かれることは保証されません。たとえばアイテムをクエリする正しい方法50
は、user_orders_query(user_id, start, limit)` を実装することです。
理解していただければ幸いです。