Fast Python bindings for the UnQLite embedded NoSQL database.
Efficient database traversal and iteration capabilities for large datasets with positioning and filtering support. Cursors provide low-level access for manual record traversal and bulk operations.
Create and manage database cursors for efficient traversal.
def cursor(self):
"""Create a cursor for iterating through the database.
Returns Cursor object."""
...
class Cursor:
def __enter__(self):
"""Enter context manager. Resets cursor position."""
...
def __exit__(self, exc_type, exc_val, exc_tb):
"""Exit context manager."""
...Usage Example:
db = unqlite.UnQLite(':mem:')
# Add test data
for i in range(10):
db[f'key{i:02d}'] = f'value{i}'
# Create and use cursor
cursor = db.cursor()
# Use as context manager for automatic cleanup
with db.cursor() as cursor:
cursor.first()
while cursor.is_valid():
key = cursor.key()
value = cursor.value()
print(f"{key}: {value}")
try:
cursor.next_entry()
except StopIteration:
breakMove cursor to specific positions within the database.
def reset(self):
"""Reset the cursor's position."""
...
def seek(self, key, flags=UNQLITE_CURSOR_MATCH_EXACT):
"""Seek to the given key using specified matching flags."""
...
def first(self):
"""Set cursor to the first record in the database."""
...
def last(self):
"""Set cursor to the last record in the database."""
...Usage Example:
db = unqlite.UnQLite(':mem:')
# Add sorted test data
keys = ['apple', 'banana', 'cherry', 'date', 'elderberry']
for key in keys:
db[key] = f'fruit:{key}'
with db.cursor() as cursor:
# Move to first record
cursor.first()
print(f"First: {cursor.key()} = {cursor.value()}")
# Move to last record
cursor.last()
print(f"Last: {cursor.key()} = {cursor.value()}")
# Seek to specific key
cursor.seek('cherry')
print(f"Found: {cursor.key()} = {cursor.value()}")
# Seek with different matching modes
cursor.seek('c', flags=unqlite.UNQLITE_CURSOR_MATCH_GE) # Greater or equal
print(f"First key >= 'c': {cursor.key()}")Navigate between records sequentially.
def next_entry(self):
"""Move cursor to the next entry. Raises StopIteration at end."""
...
def previous_entry(self):
"""Move cursor to the previous entry. Raises StopIteration at beginning."""
...
def is_valid(self):
"""Return True if cursor points to a valid record."""
...Usage Example:
db = unqlite.UnQLite(':mem:')
# Add test data
for i in range(5):
db[f'item{i}'] = f'data{i}'
with db.cursor() as cursor:
# Forward iteration
cursor.first()
print("Forward iteration:")
while cursor.is_valid():
print(f" {cursor.key()}: {cursor.value()}")
try:
cursor.next_entry()
except StopIteration:
break
# Backward iteration
cursor.last()
print("Backward iteration:")
while cursor.is_valid():
print(f" {cursor.key()}: {cursor.value()}")
try:
cursor.previous_entry()
except StopIteration:
breakAccess key and value data at cursor's current position.
def key(self):
"""Retrieve the key at the cursor's current location."""
...
def value(self):
"""Retrieve the value at the cursor's current location."""
...
def delete(self):
"""Delete the record at the cursor's current location."""
...Usage Example:
db = unqlite.UnQLite(':mem:')
# Add test data with different types
db['string_key'] = 'text_value'
db['json_key'] = '{"type": "json", "valid": true}'
db['binary_key'] = b'\x00\x01\x02\x03'
with db.cursor() as cursor:
cursor.first()
while cursor.is_valid():
key = cursor.key()
value = cursor.value()
print(f"Key: {key} (type: {type(key)})")
print(f"Value: {value} (type: {type(value)})")
# Delete specific records
if key == 'binary_key':
cursor.delete()
print("Deleted binary record")
else:
try:
cursor.next_entry()
except StopIteration:
breakUse cursors as Python iterators for convenient traversal.
def __iter__(self):
"""Return iterator for cursor."""
...
def __next__(self):
"""Get next key-value pair. Raises StopIteration at end."""
...
def fetch_until(self, stop_key, include_stop_key=True):
"""Iterate until specified key is reached."""
...Usage Example:
db = unqlite.UnQLite(':mem:')
# Add range of data
for i in range(20):
db[f'record{i:03d}'] = f'data_{i}'
# Iterate using cursor as iterator
with db.cursor() as cursor:
print("All records:")
for key, value in cursor:
print(f" {key}: {value}")
# Partial iteration with fetch_until
with db.cursor() as cursor:
cursor.seek('record005')
print("Records from record005 to record010:")
for key, value in cursor.fetch_until('record010'):
print(f" {key}: {value}")UnQLite provides convenient iteration methods that use cursors internally.
def keys(self):
"""Efficiently iterate through the database's keys."""
...
def values(self):
"""Efficiently iterate through the database's values."""
...
def items(self):
"""Efficiently iterate through the database's key-value pairs."""
...
def range(self, start_key, end_key, include_end_key=True):
"""Iterate over a range of keys."""
...
def __iter__(self):
"""Return iterator for database keys."""
...Usage Example:
db = unqlite.UnQLite(':mem:')
# Add test data
data = {'alpha': '1', 'beta': '2', 'gamma': '3', 'delta': '4'}
db.update(data)
# Iterate over keys only
print("Keys:")
for key in db.keys():
print(f" {key}")
# Iterate over values only
print("Values:")
for value in db.values():
print(f" {value}")
# Iterate over key-value pairs
print("Items:")
for key, value in db.items():
print(f" {key}: {value}")
# Range iteration
print("Range from 'beta' to 'gamma':")
for key, value in db.range('beta', 'gamma'):
print(f" {key}: {value}")
# Database as iterator (keys only)
print("Database iteration:")
for key in db:
print(f" {key}: {db[key]}")Control how the cursor positions itself when seeking to keys.
# Exact match (default)
unqlite.UNQLITE_CURSOR_MATCH_EXACT
# Less than or equal to key
unqlite.UNQLITE_CURSOR_MATCH_LE
# Greater than or equal to key
unqlite.UNQLITE_CURSOR_MATCH_GEUsage Example:
db = unqlite.UnQLite(':mem:')
# Add sorted data
keys = ['aardvark', 'bear', 'cat', 'dog', 'elephant']
for key in keys:
db[key] = f'animal:{key}'
with db.cursor() as cursor:
# Find exact match
try:
cursor.seek('cat', unqlite.UNQLITE_CURSOR_MATCH_EXACT)
print(f"Exact match: {cursor.key()}")
except:
print("Exact match not found")
# Find first key >= 'cow' (will find 'dog')
cursor.seek('cow', unqlite.UNQLITE_CURSOR_MATCH_GE)
print(f"First key >= 'cow': {cursor.key()}")
# Find last key <= 'cow' (will find 'cat')
cursor.seek('cow', unqlite.UNQLITE_CURSOR_MATCH_LE)
print(f"Last key <= 'cow': {cursor.key()}")Cursors are highly efficient for:
db = unqlite.UnQLite('large.db')
# Efficient: Use cursor for large dataset processing
with db.cursor() as cursor:
for key, value in cursor:
# Process each record efficiently
process_record(key, value)
# Inefficient: Individual key lookups
for key in db.keys(): # This internally uses a cursor
value = db[key] # This is an additional lookup
process_record(key, value)Cursor operations handle various error conditions:
db = unqlite.UnQLite(':mem:')
with db.cursor() as cursor:
try:
# Movement operations raise StopIteration at boundaries
cursor.first()
while True:
print(cursor.key())
cursor.next_entry() # Will eventually raise StopIteration
except StopIteration:
print("Reached end of database")
try:
# Seek operations may raise exceptions for invalid keys
cursor.seek('nonexistent_key')
except unqlite.UnQLiteError as e:
print(f"Seek failed: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-unqlite