<div align="center">

# RushDB Python SDK



RushDB is an instant database for modern apps and DS/ML ops built on top of Neo4j.
It automates data normalization, manages relationships, and infers data types.
[📖 Documentation](https://docs.rushdb.com/python-sdk/introduction) • [🌐 Website](https://rushdb.com) • [☁️ Cloud Platform](https://app.rushdb.com)
</div>
## Installation
```sh
pip install rushdb
```
## Quick Start
```python
from rushdb import RushDB
# Initialize the client
db = RushDB("RUSHDB_API_KEY")
# Create a record
user = db.records.create(
label="USER",
data={
"name": "John Doe",
"email": "john@example.com",
"age": 30
}
)
# Find records
result = db.records.find({
"where": {
"age": {"$gte": 18},
"name": {"$startsWith": "J"}
},
"limit": 10
})
# Work with SearchResult
print(f"Found {len(result)} records out of {result.total} total")
# Iterate over results
for record in result:
print(f"User: {record.get('name')} (Age: {record.get('age')})")
# Check if there are more results
if result.has_more:
print("There are more records available")
# Access specific records
first_user = result[0] if result else None
# Create relationships
company = db.records.create(
label="COMPANY",
data={"name": "Acme Inc."}
)
# Attach records with a relationship
user.attach(
target=company,
options={"type": "WORKS_AT", "direction": "out"}
)
```
## Pushing Nested JSON
RushDB automatically normalizes nested objects into a graph structure:
```python
# Push nested JSON with automatic relationship creation
db.records.create_many("COMPANY", {
"name": "Google LLC",
"rating": 4.9,
"DEPARTMENT": [{
"name": "Research & Development",
"PROJECT": [{
"name": "Bard AI",
"EMPLOYEE": [{
"name": "Jeff Dean",
"position": "Head of AI Research"
}]
}]
}]
})
```
## SearchResult API
RushDB Python SDK uses a modern `SearchResult` container that follows Python SDK best practices similar to boto3, google-cloud libraries, and other popular SDKs.
### SearchResult Features
- **Generic type support**: Uses Python's typing generics (`SearchResult[T]`) with `RecordSearchResult` as a type alias for `SearchResult[Record]`
- **List-like access**: Index, slice, and iterate like a regular list
- **Search context**: Access total count, pagination info, and the original search query
- **Boolean conversion**: Use in if statements naturally (returns `True` if the result contains any items)
- **Pagination support**: Built-in pagination information and `has_more` property
### Basic Usage
```python
# Perform a search
result = db.records.find({
"where": {"status": "active"},
"limit": 10,
"skip": 20
})
# Check if we have results
if result:
print(f"Found {len(result)} records")
# Access search result information
print(f"Total matching records: {result.total}")
print(f"Has more results: {result.has_more}")
print(f"Search query: {result.search_query}")
# Get detailed pagination info
page_info = result.get_page_info()
print(f"Page info: {page_info}")
# Iterate over results
for record in result:
print(f"Record: {record.get('name')}")
# List comprehensions work
names = [r.get('name') for r in result]
# Indexing and slicing
first_record = result[0] if result else None
first_five = result[:5]
# String representation
print(repr(result)) # SearchResult(count=10, total=42)
```
### SearchResult Constructor
```python
def __init__(
self,
data: List[T],
total: Optional[int] = None,
search_query: Optional[SearchQuery] = None,
):
"""
Initialize search result.
Args:
data: List of result items
total: Total number of matching records (defaults to len(data) if not provided)
search_query: The search query used to generate this result (defaults to {})
"""
```
### SearchResult Properties
| Property | Type | Description |
| -------------- | ------------- | ---------------------------------------- |
| `data` | `List[T]` | The list of result items (generic type) |
| `total` | `int` | Total number of matching records |
| `has_more` | `bool` | Whether there are more records available |
| `search_query` | `SearchQuery` | The search query used to generate result |
### SearchResult Methods
| Method | Return Type | Description |
| ----------------- | ----------- | --------------------------------------------------------- |
| `to_dict()` | `dict` | Returns standardized dict with total, data, search_query |
| `get_page_info()` | `dict` | Returns pagination info including total, loaded, has_more |
> **Implementation Notes:**
>
> - If `search_query` is not provided during initialization, it defaults to an empty dictionary `{}`
> - The `has_more` property is calculated by comparing total with loaded records
> - The `__bool__` method returns `True` if the result contains any items (`len(data) > 0`)
> - `get_page_info()` provides detailed pagination metadata for advanced use cases
### Pagination Example
```python
# Paginated search using skip/limit in query
def paginate_results(query_base, page_size=10):
current_skip = 0
while True:
# Add pagination to query
query = {**query_base, "limit": page_size, "skip": current_skip}
result = db.records.find(query)
if not result:
break
print(f"Processing {len(result)} records (skip: {current_skip})")
for record in result:
process_record(record)
if not result.has_more:
break
current_skip += len(result)
# Usage
paginate_results({
"where": {"category": "electronics"},
"orderBy": {"created_at": "desc"}
})
```
### RecordSearchResult Type
The SDK provides a specialized type alias for search results containing Record objects:
```python
# Type alias for record search results
RecordSearchResult = SearchResult[Record]
```
This type is what's returned by methods like `db.records.find()`, providing type safety and specialized handling for Record objects while leveraging all the functionality of the generic SearchResult class.
## Improved Record API
The Record class has been enhanced with better data access patterns and utility methods.
### Enhanced Data Access
```python
# Create a record
user = db.records.create("User", {
"name": "John Doe",
"email": "john@example.com",
"age": 30,
"department": "Engineering"
})
# Safe field access with defaults
name = user.get("name") # "John Doe"
phone = user.get("phone", "Not provided") # "Not provided"
# Get clean user data (excludes internal fields like __id, __label)
user_data = user.get_data()
# Returns: {"name": "John Doe", "email": "john@example.com", "age": 30, "department": "Engineering"}
# Get all data including internal fields
full_data = user.get_data(exclude_internal=False)
# Includes: __id, __label, __proptypes, etc.
# Convenient fields property
fields = user.fields # Same as user.get_data()
# Dictionary conversion
user_dict = user.to_dict() # Clean user data
full_dict = user.to_dict(exclude_internal=False) # All data
# Direct field access
user_name = user["name"] # Direct access
user_id = user["__id"] # Internal field access
```
### Record Existence Checking
```python
# Safe existence checking (no exceptions)
if user.exists():
print("Record is valid and accessible")
user.update({"status": "active"})
else:
print("Record doesn't exist or is not accessible")
# Perfect for validation workflows
def process_record_safely(record):
if not record.exists():
return None
return record.get_data()
# Conditional operations
records = db.records.find({"where": {"status": "pending"}})
for record in records:
if record.exists():
record.update({"processed_at": datetime.now()})
```
### String Representations
```python
user = db.records.create("User", {"name": "Alice Johnson"})
print(repr(user)) # Record(id='abc-123', label='User')
print(str(user)) # User: Alice Johnson
# For records without names
product = db.records.create("Product", {"sku": "ABC123"})
print(str(product)) # Product (product-id-here)
```
## Complete Documentation
For comprehensive documentation, tutorials, and examples, please visit:
**[docs.rushdb.com/python-sdk](https://docs.rushdb.com/python-sdk/introduction)**
Documentation includes:
- Complete Records API reference
- Relationship management
- Complex query examples
- Transaction usage
- Vector search capabilities
- Data import tools
## Support
- [GitHub Issues](https://github.com/rush-db/rushdb-python/issues) - Bug reports and feature requests
- [Discord Community](https://discord.gg/rushdb) - Get help from the community
- [Email Support](mailto:support@rushdb.com) - Direct support from the RushDB team
---
<div align="center">
<p>
<a href="https://docs.rushdb.com/python-sdk/introduction">
<img src="https://img.shields.io/badge/Full_Documentation-docs.rushdb.com-6D28D9?style=for-the-badge" alt="View Documentation" />
</a>
</p>
</div>
### set()
Updates a record by ID, replacing all data.
**Signature:**
```python
def set(
self,
record_id: str,
data: Dict[str, Any],
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `record_id` (str): ID of the record to update
- `data` (Dict[str, Any]): New record data
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
# Update entire record data
new_data = {
"name": "Updated Company Name",
"rating": 5.0
}
response = db.records.set(
record_id="record-123",
data=new_data
)
```
### update()
Updates specific fields of a record by ID.
**Signature:**
```python
def update(
self,
record_id: str,
data: Dict[str, Any],
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `record_id` (str): ID of the record to update
- `data` (Dict[str, Any]): Partial record data to update
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
# Update specific fields
updates = {
"rating": 4.8,
"status": "active"
}
response = db.records.update(
record_id="record-123",
data=updates
)
```
### find()
Searches for records matching specified criteria.
**Signature:**
```python
def find(
self,
search_query: Optional[SearchQuery] = None,
record_id: Optional[str] = None,
transaction: Optional[Transaction] = None
) -> RecordSearchResult
```
**Arguments:**
- `search_query` (Optional[SearchQuery]): Search query parameters
- `record_id` (Optional[str]): Optional record ID to search from
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `RecordSearchResult`: SearchResult container with matching records and metadata
**Example:**
```python
# Search for records with complex criteria
search_query = {
"where": {
"$and": [
{"age": {"$gte": 18}},
{"status": "active"},
{"department": "Engineering"}
]
},
"orderBy": {"created_at": "desc"},
"limit": 10
}
result = db.records.find(search_query=search_query)
# Work with SearchResult
print(f"Found {len(result)} out of {result.total} total records")
# Iterate over results
for record in result:
print(f"Employee: {record.get('name')} - {record.get('department')}")
# Check pagination
if result.has_more:
print("More results available")
# Access specific records
first_employee = result[0] if result else None
# List operations
senior_employees = [r for r in result if r.get('age', 0) > 30]
```
### delete()
Deletes records matching a query.
**Signature:**
```python
def delete(
self,
search_query: SearchQuery,
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `search_query` (SearchQuery): Query to match records for deletion
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
# Delete records matching criteria
search_query = {
"where": {
"status": "inactive",
"lastActive": {"$lt": "2023-01-01"}
}
}
response = db.records.delete(search_query)
```
### delete_by_id()
Deletes one or more records by ID.
**Signature:**
```python
def delete_by_id(
self,
id_or_ids: Union[str, List[str]],
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `id_or_ids` (Union[str, List[str]]): Single ID or list of IDs to delete
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
# Delete single record
response = db.records.delete_by_id("record-123")
# Delete multiple records
response = db.records.delete_by_id([
"record-123",
"record-456",
"record-789"
])
```
### attach()
Creates relationships between records.
**Signature:**
```python
def attach(
self,
source: Union[str, Dict[str, Any]],
target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]],
options: Optional[RelationshipOptions] = None,
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `source` (Union[str, Dict[str, Any]]): Source record ID or data
- `target` (Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]]): Target record(s)
- `options` (Optional[RelationshipOptions]): Relationship options
- `direction` (Optional[Literal["in", "out"]]): Relationship direction
- `type` (Optional[str]): Relationship type
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
# Create relationship between records
options = RelationshipOptions(
type="HAS_EMPLOYEE",
direction="out"
)
response = db.records.attach(
source="company-123",
target=["employee-456", "employee-789"],
options=options
)
```
### detach()
Removes relationships between records.
**Signature:**
```python
def detach(
self,
source: Union[str, Dict[str, Any]],
target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]],
options: Optional[RelationshipDetachOptions] = None,
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `source` (Union[str, Dict[str, Any]]): Source record ID or data
- `target` (Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]]): Target record(s)
- `options` (Optional[RelationshipDetachOptions]): Detach options
- `direction` (Optional[Literal["in", "out"]]): Relationship direction
- `typeOrTypes` (Optional[Union[str, List[str]]]): Relationship type(s)
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
# Remove relationships between records
options = RelationshipDetachOptions(
typeOrTypes=["HAS_EMPLOYEE", "MANAGES"],
direction="out"
)
response = db.records.detach(
source="company-123",
target="employee-456",
options=options
)
```
### import_csv()
Imports records from CSV data.
**Signature:**
```python
def import_csv(
self,
label: str,
data: str,
options: Optional[Dict[str, bool]] = None,
transaction: Optional[Transaction] = None
) -> List[Dict[str, Any]]
```
**Arguments:**
- `label` (str): Label for imported records
- `data` (Union[str, bytes]): CSV data to import
- `options` (Optional[Dict[str, bool]]): Import options
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `List[Dict[str, Any]]`: Imported records data
**Example:**
```python
# Import records from CSV
data = """name,age,department,role
John Doe,30,Engineering,Senior Engineer
Jane Smith,28,Product,Product Manager
Bob Wilson,35,Engineering,Tech Lead"""
records = db.records.import_csv(
label="EMPLOYEE",
data=data,
options={"returnResult": True, "suggestTypes": True}
)
```
---
# Record Class Documentation
The `Record` class represents a record in RushDB and provides methods for manipulating individual records, including updates, relationships, and deletions.
## Class Definition
```python
class Record:
def __init__(self, client: "RushDB", data: Union[Dict[str, Any], None] = None)
```
## Properties
### id
Gets the record's unique identifier.
**Type:** `str`
**Example:**
```python
record = db.records.create("USER", {"name": "John"})
print(record.id) # e.g., "1234abcd-5678-..."
```
### proptypes
Gets the record's property types.
**Type:** `str`
**Example:**
```python
record = db.records.create("USER", {"name": "John", "age": 25})
print(record.proptypes) # Returns property type definitions
```
### label
Gets the record's label.
**Type:** `str`
**Example:**
```python
record = db.records.create("USER", {"name": "John"})
print(record.label) # "USER"
```
### timestamp
Gets the record's creation timestamp from its ID.
**Type:** `int`
**Example:**
```python
record = db.records.create("USER", {"name": "John"})
print(record.timestamp) # Unix timestamp in milliseconds
```
### date
Gets the record's creation date.
**Type:** `datetime`
**Example:**
```python
record = db.records.create("USER", {"name": "John"})
print(record.date) # datetime object
```
## Methods
### set()
Updates all data for the record.
**Signature:**
```python
def set(
self,
data: Dict[str, Any],
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `data` (Dict[str, Any]): New record data
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
record = db.records.create("USER", {"name": "John"})
response = record.set({
"name": "John Doe",
"email": "john@example.com",
"age": 30
})
```
### update()
Updates specific fields of the record.
**Signature:**
```python
def update(
self,
data: Dict[str, Any],
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `data` (Dict[str, Any]): Partial record data to update
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
record = db.records.create("USER", {
"name": "John",
"email": "john@example.com"
})
response = record.update({
"email": "john.doe@example.com"
})
```
### attach()
Creates relationships with other records.
**Signature:**
```python
def attach(
self,
target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], "Record", List["Record"]],
options: Optional[RelationshipOptions] = None,
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `target` (Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]]): Target record(s)
- `options` (Optional[RelationshipOptions]): Relationship options
- `direction` (Optional[Literal["in", "out"]]): Relationship direction
- `type` (Optional[str]): Relationship type
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
# Create two records
user = db.records.create("USER", {"name": "John"})
group = db.records.create("GROUP", {"name": "Admins"})
# Attach user to group
response = user.attach(
target=group,
options=RelationshipOptions(
type="BELONGS_TO",
direction="out"
)
)
```
### detach()
Removes relationships with other records.
**Signature:**
```python
def detach(
self,
target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], "Record", List["Record"]],
options: Optional[RelationshipDetachOptions] = None,
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `target` (Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]]): Target record(s)
- `options` (Optional[RelationshipDetachOptions]): Detach options
- `direction` (Optional[Literal["in", "out"]]): Relationship direction
- `typeOrTypes` (Optional[Union[str, List[str]]]): Relationship type(s)
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
# Detach user from group
response = user.detach(
target=group,
options=RelationshipDetachOptions(
typeOrTypes="BELONGS_TO",
direction="out"
)
)
```
### delete()
Deletes the record.
**Signature:**
```python
def delete(
self,
transaction: Optional[Transaction] = None
) -> Dict[str, str]
```
**Arguments:**
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, str]`: Response data
**Example:**
```python
user = db.records.create("USER", {"name": "John"})
response = user.delete()
```
## Complete Usage Example
Here's a comprehensive example demonstrating various Record operations:
```python
# Create a new record
user = db.records.create("USER", {
"name": "John Doe",
"email": "john@example.com",
"age": 30
})
# Access properties
print(f"Record ID: {user.id}")
print(f"Label: {user.label}")
print(f"Created at: {user.date}")
# Update record data
user.update({
"age": 31,
"title": "Senior Developer"
})
# Create related records
department = db.records.create("DEPARTMENT", {
"name": "Engineering"
})
project = db.records.create("PROJECT", {
"name": "Secret Project"
})
# Create relationships
user.attach(
target=department,
options=RelationshipOptions(
type="BELONGS_TO",
direction="out"
)
)
user.attach(
target=project,
options=RelationshipOptions(
type="WORKS_ON",
direction="out"
)
)
# Remove relationship
user.detach(
target=project,
options=RelationshipDetachOptions(
typeOrTypes="WORKS_ON",
direction="out"
)
)
# Delete record
user.delete()
```
## Working with Transactions
Records can be manipulated within transactions for atomic operations:
```python
# Start a transaction
transaction = db.transactions.begin()
try:
# Create user
user = db.records.create(
"USER",
{"name": "John Doe"},
transaction=transaction
)
# Update user
user.update(
{"status": "active"},
transaction=transaction
)
# Create and attach department
dept = db.records.create(
"DEPARTMENT",
{"name": "Engineering"},
transaction=transaction
)
user.attach(
target=dept,
options=RelationshipOptions(type="BELONGS_TO"),
transaction=transaction
)
# Explicitly commit the transaction to make changes permanent
transaction.commit()
except Exception as e:
# Rollback if any error occurs
transaction.rollback()
raise e
# Alternative: Using context manager
with db.transactions.begin() as transaction:
# Perform operations...
user = db.records.create(
"USER",
{"name": "John Doe"},
transaction=transaction
)
# Must explicitly commit - transactions are NOT automatically committed
transaction.commit()
```
---
# PropertiesAPI Documentation
The `PropertiesAPI` class provides methods for managing and querying properties in RushDB.
## Class Definition
```python
class PropertiesAPI(BaseAPI):
```
## Methods
### find()
Retrieves a list of properties based on optional search criteria.
**Signature:**
```python
def find(
self,
search_query: Optional[SearchQuery] = None,
transaction: Optional[Transaction] = None
) -> List[Property]
```
**Arguments:**
- `query` (Optional[SearchQuery]): Search query parameters for filtering properties
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `List[Property]`: List of properties matching the search criteria
**Example:**
```python
# Find all properties
properties = db.properties.find()
# Find properties with specific criteria
query = {
"where": {
"name": {"$startsWith": "user_"}, # Properties starting with 'user_'
"type": "string" # Only string type properties
},
"limit": 10 # Limit to 10 results
}
filtered_properties = db.properties.find(query)
```
### find_by_id()
Retrieves a specific property by its ID.
**Signature:**
```python
def find_by_id(
self,
property_id: str,
transaction: Optional[Transaction] = None
) -> Property
```
**Arguments:**
- `property_id` (str): Unique identifier of the property
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Property`: Property details
**Example:**
```python
# Retrieve a specific property by ID
property_details = db.properties.find_by_id("prop_123456")
```
### delete()
Deletes a property by its ID.
**Signature:**
```python
def delete(
self,
property_id: str,
transaction: Optional[Transaction] = None
) -> None
```
**Arguments:**
- `property_id` (str): Unique identifier of the property to delete
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `None`
**Example:**
```python
# Delete a property
db.properties.delete("prop_123456")
```
### values()
Retrieves values for a specific property with optional sorting and pagination.
**Signature:**
```python
def values(
self,
property_id: str,
sort: Optional[Literal["asc", "desc"]] = None,
skip: Optional[int] = None,
limit: Optional[int] = None,
transaction: Optional[Transaction] = None
) -> PropertyValuesData
```
**Arguments:**
- `property_id` (str): Unique identifier of the property
- `sort` (Optional[Literal["asc", "desc"]]): Sort order of values
- `skip` (Optional[int]): Number of values to skip (for pagination)
- `limit` (Optional[int]): Maximum number of values to return
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `PropertyValuesData`: Property values data, including optional min/max and list of values
**Example:**
```python
# Get property values
values_data = db.properties.values(
property_id="prop_age",
sort="desc", # Sort values in descending order
skip=0, # Start from the first value
limit=100 # Return up to 100 values
)
# Access values
print(values_data.get('values', [])) # List of property values
print(values_data.get('min')) # Minimum value (for numeric properties)
print(values_data.get('max')) # Maximum value (for numeric properties)
```
## Comprehensive Usage Example
```python
# Find all properties
all_properties = db.properties.find()
for prop in all_properties:
print(f"Property ID: {prop['id']}")
print(f"Name: {prop['name']}")
print(f"Type: {prop['type']}")
print(f"Metadata: {prop.get('metadata', 'No metadata')}")
print("---")
# Detailed property search
query = {
"where": {
"type": "number", # Only numeric properties
"name": {"$contains": "score"} # Properties with 'score' in name
},
"limit": 5 # Limit to 5 results
}
numeric_score_properties = db.properties.find(query)
# Get values for a specific property
if numeric_score_properties:
first_prop = numeric_score_properties[0]
prop_values = db.properties.values(
property_id=first_prop['id'],
sort="desc",
limit=50
)
print(f"Values for {first_prop['name']}:")
print(f"Min: {prop_values.get('min')}")
print(f"Max: {prop_values.get('max')}")
# Detailed property examination
detailed_prop = db.properties.find_by_id(first_prop['id'])
print("Detailed Property Info:", detailed_prop)
```
## Property Types and Structures
RushDB supports the following property types:
- `"boolean"`: True/False values
- `"datetime"`: Date and time values
- `"null"`: Null/empty values
- `"number"`: Numeric values
- `"string"`: Text values
### Property Structure Example
```python
property = {
"id": "prop_unique_id",
"name": "user_score",
"type": "number",
"metadata": Optional[str] # Optional additional information
}
property_with_value = {
"id": "prop_unique_id",
"name": "user_score",
"type": "number",
"value": 95.5 # Actual property value
}
```
## Transactions
Properties API methods support optional transactions for atomic operations:
```python
# Using a transaction with explicit commit
transaction = db.transactions.begin()
try:
# Perform multiple property-related operations
property_to_delete = db.properties.find(
{"where": {"name": "temp_property"}},
transaction=transaction
)[0]
db.properties.delete(
property_id=property_to_delete['id'],
transaction=transaction
)
# Explicitly commit the transaction
transaction.commit()
except Exception as e:
# Rollback if any error occurs
transaction.rollback()
raise e
# Alternative: Using context manager (auto-rollback on error)
with db.transactions.begin() as transaction:
# Perform operations
property_to_delete = db.properties.find(
{"where": {"name": "temp_property"}},
transaction=transaction
)[0]
db.properties.delete(
property_id=property_to_delete['id'],
transaction=transaction
)
# Must explicitly commit - transactions are NOT automatically committed
transaction.commit()
```
## Error Handling
When working with the PropertiesAPI, be prepared to handle potential errors:
```python
try:
# Attempt to find or delete a property
property_details = db.properties.find_by_id("non_existent_prop")
except RushDBError as e:
print(f"Error: {e}")
print(f"Error Details: {e.details}")
```
---
# LabelsAPI Documentation
The `LabelsAPI` class provides methods for discovering and working with record labels in RushDB. Labels are used to categorize and type records, similar to table names in relational databases.
## Class Definition
```python
class LabelsAPI(BaseAPI):
```
## Methods
### find()
Discovers labels (record types) that exist in the database and can optionally filter them based on search criteria.
**Signature:**
```python
def find(
self,
search_query: Optional[SearchQuery] = None,
transaction: Optional[Transaction] = None
) -> Dict[str, int]
```
**Arguments:**
- `search_query` (Optional[SearchQuery]): Search criteria to filter labels
- `transaction` (Optional[Transaction]): Optional transaction object
**Returns:**
- `Dict[str, int]`: Dictionary mapping label names to their record counts
**Example:**
```python
# Get all labels in the database
all_labels = db.labels.find()
print("Available labels:", all_labels)
# Output: {'USER': 150, 'DEPARTMENT': 12, 'PROJECT': 45, 'COMPANY': 3}
# Search for labels amongst records matching a pattern
from rushdb.models.search_query import SearchQuery
query = SearchQuery(where={"name": {"$contains": "alice"}})
user_labels = db.labels.find(query)
print("Labels for records containing 'alice':", user_labels)
# Output: {'USER': 2, 'EMPLOYEE': 1}
```
## Complete Usage Example
```python
# Discover all record types in the database
all_labels = db.labels.find()
print(f"Database contains {len(all_labels)} record types:")
for label, count in all_labels.items():
print(f" - {label}: {count} records")
# Find labels for records with specific criteria
query = SearchQuery(where={
"status": "active",
"created_date": {"$gte": "2023-01-01"}
})
active_labels = db.labels.find(query)
print("Labels for active records:")
for label, count in active_labels.items():
print(f" - {label}: {count} active records")
# Use with transaction
transaction = db.transactions.begin()
try:
labels_in_tx = db.labels.find(transaction=transaction)
# Process labels...
transaction.commit()
except Exception as e:
transaction.rollback()
raise e
```
---
# RelationshipsAPI Documentation
The `RelationshipsAPI` class provides functionality for querying and analyzing relationships between records in RushDB. Relationships represent connections or associations between different records.
## Class Definition
```python
class RelationshipsAPI(BaseAPI):
```
## Methods
### find()
Search for and retrieve relationships matching the specified criteria with support for pagination and transactions.
**Signature:**
```python
async def find(
self,
search_query: Optional[SearchQuery] = None,
pagination: Optional[PaginationParams] = None,
transaction: Optional[Union[Transaction, str]] = None
) -> List[Relationship]
```
**Arguments:**
- `search_query` (Optional[SearchQuery]): Search criteria to filter relationships
- `pagination` (Optional[PaginationParams]): Pagination options with `limit` and `skip`
- `transaction` (Optional[Union[Transaction, str]]): Optional transaction object or ID
**Returns:**
- `List[Relationship]`: List of relationships matching the search criteria
**Example:**
```python
import asyncio
from rushdb.models.search_query import SearchQuery
async def main():
# Find all relationships
all_relationships = await db.relationships.find()
print(f"Total relationships: {len(all_relationships)}")
# Find relationships with pagination
pagination = {"limit": 50, "skip": 0}
first_page = await db.relationships.find(pagination=pagination)
# Find specific relationship types
query = SearchQuery(where={"type": "BELONGS_TO"})
belongs_to_rels = await db.relationships.find(search_query=query)
# Find relationships involving specific records
user_query = SearchQuery(where={
"$or": [
{"source_id": "user-123"},
{"target_id": "user-123"}
]
})
user_relationships = await db.relationships.find(search_query=user_query)
# Run the async function
asyncio.run(main())
```
## PaginationParams
The `PaginationParams` TypedDict defines pagination options:
```python
class PaginationParams(TypedDict, total=False):
limit: int # Maximum number of relationships to return
skip: int # Number of relationships to skip
```
## Complete Usage Example
```python
import asyncio
from rushdb.models.search_query import SearchQuery
async def explore_relationships():
# Get overview of all relationships
all_rels = await db.relationships.find()
print(f"Database contains {len(all_rels)} relationships")
# Paginate through relationships
page_size = 25
page = 0
while True:
pagination = {"limit": page_size, "skip": page * page_size}
relationships = await db.relationships.find(pagination=pagination)
if not relationships:
break
print(f"Page {page + 1}: {len(relationships)} relationships")
for rel in relationships:
print(f" {rel['source_id']} --[{rel['type']}]--> {rel['target_id']}")
page += 1
if len(relationships) < page_size:
break
# Find relationships by type
query = SearchQuery(where={"type": "WORKS_ON"})
work_relationships = await db.relationships.find(search_query=query)
print(f"Found {len(work_relationships)} 'WORKS_ON' relationships")
# Find relationships within a transaction
transaction = db.transactions.begin()
try:
tx_rels = await db.relationships.find(transaction=transaction)
# Process relationships...
transaction.commit()
except Exception as e:
transaction.rollback()
raise e
# Run the example
asyncio.run(explore_relationships())
```
## Working with Transactions
Both LabelsAPI and RelationshipsAPI support transactions:
```python
import asyncio
async def transaction_example():
transaction = db.transactions.begin()
try:
# Find labels within transaction
labels = db.labels.find(transaction=transaction)
# Find relationships within transaction
relationships = await db.relationships.find(transaction=transaction)
# Perform operations based on discovered data...
# Explicitly commit the transaction
transaction.commit()
except Exception as e:
# Rollback on any error
transaction.rollback()
raise e
asyncio.run(transaction_example())
```
**Note:** The RelationshipsAPI methods are async and require the use of `await` and `asyncio` for proper execution.
Raw data
{
"_id": null,
"home_page": null,
"name": "rushdb",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "ai, ai database, app backend, app-backend, artificial intelligence, cloud, cypher, data analysis, data engineering, data management, data pipeline, data science, data-analysis, data-engineering, data-management, data-pipeline, data-science, database, db, embedding, embeddings, etl, fractal api, fractal-api, graph, graph database, graph-database, graphs, instant database, instant db, instant-database, instant-db, json normalization, json-normalization, machine learning, machine-learning, modern apps, modern-apps, neo4j, no-schema, persistence, rag, relationships, rest api, rest-api, retrieval augmented generation, rush db, rush-db, rushdb, schema-less, schemaless, self-hosted, similarity search, vector search, vector-search, web development, web-development",
"author": null,
"author_email": "RushDB Team <hi@rushdb.com>",
"download_url": "https://files.pythonhosted.org/packages/7e/60/df02679210dba505bd595e800a1d0edc04d6a13906bacc3a51937b17a037/rushdb-1.10.0.tar.gz",
"platform": null,
"description": "<div align=\"center\">\n\n\n\n# RushDB Python SDK\n\n\n\n\n\nRushDB is an instant database for modern apps and DS/ML ops built on top of Neo4j.\nIt automates data normalization, manages relationships, and infers data types.\n\n[\ud83d\udcd6 Documentation](https://docs.rushdb.com/python-sdk/introduction) \u2022 [\ud83c\udf10 Website](https://rushdb.com) \u2022 [\u2601\ufe0f Cloud Platform](https://app.rushdb.com)\n\n</div>\n\n## Installation\n\n```sh\npip install rushdb\n```\n\n## Quick Start\n\n```python\nfrom rushdb import RushDB\n\n# Initialize the client\ndb = RushDB(\"RUSHDB_API_KEY\")\n\n# Create a record\nuser = db.records.create(\n label=\"USER\",\n data={\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\",\n \"age\": 30\n }\n)\n\n# Find records\nresult = db.records.find({\n \"where\": {\n \"age\": {\"$gte\": 18},\n \"name\": {\"$startsWith\": \"J\"}\n },\n \"limit\": 10\n})\n\n# Work with SearchResult\nprint(f\"Found {len(result)} records out of {result.total} total\")\n\n# Iterate over results\nfor record in result:\n print(f\"User: {record.get('name')} (Age: {record.get('age')})\")\n\n# Check if there are more results\nif result.has_more:\n print(\"There are more records available\")\n\n# Access specific records\nfirst_user = result[0] if result else None\n\n# Create relationships\ncompany = db.records.create(\n label=\"COMPANY\",\n data={\"name\": \"Acme Inc.\"}\n)\n\n# Attach records with a relationship\nuser.attach(\n target=company,\n options={\"type\": \"WORKS_AT\", \"direction\": \"out\"}\n)\n```\n\n## Pushing Nested JSON\n\nRushDB automatically normalizes nested objects into a graph structure:\n\n```python\n# Push nested JSON with automatic relationship creation\ndb.records.create_many(\"COMPANY\", {\n \"name\": \"Google LLC\",\n \"rating\": 4.9,\n \"DEPARTMENT\": [{\n \"name\": \"Research & Development\",\n \"PROJECT\": [{\n \"name\": \"Bard AI\",\n \"EMPLOYEE\": [{\n \"name\": \"Jeff Dean\",\n \"position\": \"Head of AI Research\"\n }]\n }]\n }]\n})\n```\n\n## SearchResult API\n\nRushDB Python SDK uses a modern `SearchResult` container that follows Python SDK best practices similar to boto3, google-cloud libraries, and other popular SDKs.\n\n### SearchResult Features\n\n- **Generic type support**: Uses Python's typing generics (`SearchResult[T]`) with `RecordSearchResult` as a type alias for `SearchResult[Record]`\n- **List-like access**: Index, slice, and iterate like a regular list\n- **Search context**: Access total count, pagination info, and the original search query\n- **Boolean conversion**: Use in if statements naturally (returns `True` if the result contains any items)\n- **Pagination support**: Built-in pagination information and `has_more` property\n\n### Basic Usage\n\n```python\n# Perform a search\nresult = db.records.find({\n \"where\": {\"status\": \"active\"},\n \"limit\": 10,\n \"skip\": 20\n})\n\n# Check if we have results\nif result:\n print(f\"Found {len(result)} records\")\n\n# Access search result information\nprint(f\"Total matching records: {result.total}\")\nprint(f\"Has more results: {result.has_more}\")\nprint(f\"Search query: {result.search_query}\")\n\n# Get detailed pagination info\npage_info = result.get_page_info()\nprint(f\"Page info: {page_info}\")\n\n# Iterate over results\nfor record in result:\n print(f\"Record: {record.get('name')}\")\n\n# List comprehensions work\nnames = [r.get('name') for r in result]\n\n# Indexing and slicing\nfirst_record = result[0] if result else None\nfirst_five = result[:5]\n\n# String representation\nprint(repr(result)) # SearchResult(count=10, total=42)\n```\n\n### SearchResult Constructor\n\n```python\ndef __init__(\n self,\n data: List[T],\n total: Optional[int] = None,\n search_query: Optional[SearchQuery] = None,\n):\n \"\"\"\n Initialize search result.\n\n Args:\n data: List of result items\n total: Total number of matching records (defaults to len(data) if not provided)\n search_query: The search query used to generate this result (defaults to {})\n \"\"\"\n```\n\n### SearchResult Properties\n\n| Property | Type | Description |\n| -------------- | ------------- | ---------------------------------------- |\n| `data` | `List[T]` | The list of result items (generic type) |\n| `total` | `int` | Total number of matching records |\n| `has_more` | `bool` | Whether there are more records available |\n| `search_query` | `SearchQuery` | The search query used to generate result |\n\n### SearchResult Methods\n\n| Method | Return Type | Description |\n| ----------------- | ----------- | --------------------------------------------------------- |\n| `to_dict()` | `dict` | Returns standardized dict with total, data, search_query |\n| `get_page_info()` | `dict` | Returns pagination info including total, loaded, has_more |\n\n> **Implementation Notes:**\n>\n> - If `search_query` is not provided during initialization, it defaults to an empty dictionary `{}`\n> - The `has_more` property is calculated by comparing total with loaded records\n> - The `__bool__` method returns `True` if the result contains any items (`len(data) > 0`)\n> - `get_page_info()` provides detailed pagination metadata for advanced use cases\n\n### Pagination Example\n\n```python\n# Paginated search using skip/limit in query\ndef paginate_results(query_base, page_size=10):\n current_skip = 0\n\n while True:\n # Add pagination to query\n query = {**query_base, \"limit\": page_size, \"skip\": current_skip}\n result = db.records.find(query)\n\n if not result:\n break\n\n print(f\"Processing {len(result)} records (skip: {current_skip})\")\n\n for record in result:\n process_record(record)\n\n if not result.has_more:\n break\n\n current_skip += len(result)\n\n# Usage\npaginate_results({\n \"where\": {\"category\": \"electronics\"},\n \"orderBy\": {\"created_at\": \"desc\"}\n})\n```\n\n### RecordSearchResult Type\n\nThe SDK provides a specialized type alias for search results containing Record objects:\n\n```python\n# Type alias for record search results\nRecordSearchResult = SearchResult[Record]\n```\n\nThis type is what's returned by methods like `db.records.find()`, providing type safety and specialized handling for Record objects while leveraging all the functionality of the generic SearchResult class.\n\n## Improved Record API\n\nThe Record class has been enhanced with better data access patterns and utility methods.\n\n### Enhanced Data Access\n\n```python\n# Create a record\nuser = db.records.create(\"User\", {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\",\n \"age\": 30,\n \"department\": \"Engineering\"\n})\n\n# Safe field access with defaults\nname = user.get(\"name\") # \"John Doe\"\nphone = user.get(\"phone\", \"Not provided\") # \"Not provided\"\n\n# Get clean user data (excludes internal fields like __id, __label)\nuser_data = user.get_data()\n# Returns: {\"name\": \"John Doe\", \"email\": \"john@example.com\", \"age\": 30, \"department\": \"Engineering\"}\n\n# Get all data including internal fields\nfull_data = user.get_data(exclude_internal=False)\n# Includes: __id, __label, __proptypes, etc.\n\n# Convenient fields property\nfields = user.fields # Same as user.get_data()\n\n# Dictionary conversion\nuser_dict = user.to_dict() # Clean user data\nfull_dict = user.to_dict(exclude_internal=False) # All data\n\n# Direct field access\nuser_name = user[\"name\"] # Direct access\nuser_id = user[\"__id\"] # Internal field access\n```\n\n### Record Existence Checking\n\n```python\n# Safe existence checking (no exceptions)\nif user.exists():\n print(\"Record is valid and accessible\")\n user.update({\"status\": \"active\"})\nelse:\n print(\"Record doesn't exist or is not accessible\")\n\n# Perfect for validation workflows\ndef process_record_safely(record):\n if not record.exists():\n return None\n return record.get_data()\n\n# Conditional operations\nrecords = db.records.find({\"where\": {\"status\": \"pending\"}})\nfor record in records:\n if record.exists():\n record.update({\"processed_at\": datetime.now()})\n```\n\n### String Representations\n\n```python\nuser = db.records.create(\"User\", {\"name\": \"Alice Johnson\"})\n\nprint(repr(user)) # Record(id='abc-123', label='User')\nprint(str(user)) # User: Alice Johnson\n\n# For records without names\nproduct = db.records.create(\"Product\", {\"sku\": \"ABC123\"})\nprint(str(product)) # Product (product-id-here)\n```\n\n## Complete Documentation\n\nFor comprehensive documentation, tutorials, and examples, please visit:\n\n**[docs.rushdb.com/python-sdk](https://docs.rushdb.com/python-sdk/introduction)**\n\nDocumentation includes:\n\n- Complete Records API reference\n- Relationship management\n- Complex query examples\n- Transaction usage\n- Vector search capabilities\n- Data import tools\n\n## Support\n\n- [GitHub Issues](https://github.com/rush-db/rushdb-python/issues) - Bug reports and feature requests\n- [Discord Community](https://discord.gg/rushdb) - Get help from the community\n- [Email Support](mailto:support@rushdb.com) - Direct support from the RushDB team\n\n---\n\n<div align=\"center\">\n <p>\n <a href=\"https://docs.rushdb.com/python-sdk/introduction\">\n <img src=\"https://img.shields.io/badge/Full_Documentation-docs.rushdb.com-6D28D9?style=for-the-badge\" alt=\"View Documentation\" />\n </a>\n </p>\n</div>\n\n### set()\n\nUpdates a record by ID, replacing all data.\n\n**Signature:**\n\n```python\ndef set(\n self,\n record_id: str,\n data: Dict[str, Any],\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `record_id` (str): ID of the record to update\n- `data` (Dict[str, Any]): New record data\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\n# Update entire record data\nnew_data = {\n \"name\": \"Updated Company Name\",\n \"rating\": 5.0\n}\n\nresponse = db.records.set(\n record_id=\"record-123\",\n data=new_data\n)\n```\n\n### update()\n\nUpdates specific fields of a record by ID.\n\n**Signature:**\n\n```python\ndef update(\n self,\n record_id: str,\n data: Dict[str, Any],\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `record_id` (str): ID of the record to update\n- `data` (Dict[str, Any]): Partial record data to update\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\n# Update specific fields\nupdates = {\n \"rating\": 4.8,\n \"status\": \"active\"\n}\n\nresponse = db.records.update(\n record_id=\"record-123\",\n data=updates\n)\n```\n\n### find()\n\nSearches for records matching specified criteria.\n\n**Signature:**\n\n```python\ndef find(\n self,\n search_query: Optional[SearchQuery] = None,\n record_id: Optional[str] = None,\n transaction: Optional[Transaction] = None\n) -> RecordSearchResult\n```\n\n**Arguments:**\n\n- `search_query` (Optional[SearchQuery]): Search query parameters\n- `record_id` (Optional[str]): Optional record ID to search from\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `RecordSearchResult`: SearchResult container with matching records and metadata\n\n**Example:**\n\n```python\n# Search for records with complex criteria\nsearch_query = {\n \"where\": {\n \"$and\": [\n {\"age\": {\"$gte\": 18}},\n {\"status\": \"active\"},\n {\"department\": \"Engineering\"}\n ]\n },\n \"orderBy\": {\"created_at\": \"desc\"},\n \"limit\": 10\n}\n\nresult = db.records.find(search_query=search_query)\n\n# Work with SearchResult\nprint(f\"Found {len(result)} out of {result.total} total records\")\n\n# Iterate over results\nfor record in result:\n print(f\"Employee: {record.get('name')} - {record.get('department')}\")\n\n# Check pagination\nif result.has_more:\n print(\"More results available\")\n\n# Access specific records\nfirst_employee = result[0] if result else None\n\n# List operations\nsenior_employees = [r for r in result if r.get('age', 0) > 30]\n```\n\n### delete()\n\nDeletes records matching a query.\n\n**Signature:**\n\n```python\ndef delete(\n self,\n search_query: SearchQuery,\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `search_query` (SearchQuery): Query to match records for deletion\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\n# Delete records matching criteria\nsearch_query = {\n \"where\": {\n \"status\": \"inactive\",\n \"lastActive\": {\"$lt\": \"2023-01-01\"}\n }\n}\n\nresponse = db.records.delete(search_query)\n```\n\n### delete_by_id()\n\nDeletes one or more records by ID.\n\n**Signature:**\n\n```python\ndef delete_by_id(\n self,\n id_or_ids: Union[str, List[str]],\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `id_or_ids` (Union[str, List[str]]): Single ID or list of IDs to delete\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\n# Delete single record\nresponse = db.records.delete_by_id(\"record-123\")\n\n# Delete multiple records\nresponse = db.records.delete_by_id([\n \"record-123\",\n \"record-456\",\n \"record-789\"\n])\n```\n\n### attach()\n\nCreates relationships between records.\n\n**Signature:**\n\n```python\ndef attach(\n self,\n source: Union[str, Dict[str, Any]],\n target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]],\n options: Optional[RelationshipOptions] = None,\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `source` (Union[str, Dict[str, Any]]): Source record ID or data\n- `target` (Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]]): Target record(s)\n- `options` (Optional[RelationshipOptions]): Relationship options\n - `direction` (Optional[Literal[\"in\", \"out\"]]): Relationship direction\n - `type` (Optional[str]): Relationship type\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\n# Create relationship between records\noptions = RelationshipOptions(\n type=\"HAS_EMPLOYEE\",\n direction=\"out\"\n)\n\nresponse = db.records.attach(\n source=\"company-123\",\n target=[\"employee-456\", \"employee-789\"],\n options=options\n)\n```\n\n### detach()\n\nRemoves relationships between records.\n\n**Signature:**\n\n```python\ndef detach(\n self,\n source: Union[str, Dict[str, Any]],\n target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]],\n options: Optional[RelationshipDetachOptions] = None,\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `source` (Union[str, Dict[str, Any]]): Source record ID or data\n- `target` (Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]]): Target record(s)\n- `options` (Optional[RelationshipDetachOptions]): Detach options\n - `direction` (Optional[Literal[\"in\", \"out\"]]): Relationship direction\n - `typeOrTypes` (Optional[Union[str, List[str]]]): Relationship type(s)\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\n# Remove relationships between records\noptions = RelationshipDetachOptions(\n typeOrTypes=[\"HAS_EMPLOYEE\", \"MANAGES\"],\n direction=\"out\"\n)\n\nresponse = db.records.detach(\n source=\"company-123\",\n target=\"employee-456\",\n options=options\n)\n```\n\n### import_csv()\n\nImports records from CSV data.\n\n**Signature:**\n\n```python\ndef import_csv(\n self,\n label: str,\n data: str,\n options: Optional[Dict[str, bool]] = None,\n transaction: Optional[Transaction] = None\n) -> List[Dict[str, Any]]\n```\n\n**Arguments:**\n\n- `label` (str): Label for imported records\n- `data` (Union[str, bytes]): CSV data to import\n- `options` (Optional[Dict[str, bool]]): Import options\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `List[Dict[str, Any]]`: Imported records data\n\n**Example:**\n\n```python\n# Import records from CSV\ndata = \"\"\"name,age,department,role\nJohn Doe,30,Engineering,Senior Engineer\nJane Smith,28,Product,Product Manager\nBob Wilson,35,Engineering,Tech Lead\"\"\"\n\nrecords = db.records.import_csv(\n label=\"EMPLOYEE\",\n data=data,\n options={\"returnResult\": True, \"suggestTypes\": True}\n)\n```\n\n---\n\n# Record Class Documentation\n\nThe `Record` class represents a record in RushDB and provides methods for manipulating individual records, including updates, relationships, and deletions.\n\n## Class Definition\n\n```python\nclass Record:\n def __init__(self, client: \"RushDB\", data: Union[Dict[str, Any], None] = None)\n```\n\n## Properties\n\n### id\n\nGets the record's unique identifier.\n\n**Type:** `str`\n\n**Example:**\n\n```python\nrecord = db.records.create(\"USER\", {\"name\": \"John\"})\nprint(record.id) # e.g., \"1234abcd-5678-...\"\n```\n\n### proptypes\n\nGets the record's property types.\n\n**Type:** `str`\n\n**Example:**\n\n```python\nrecord = db.records.create(\"USER\", {\"name\": \"John\", \"age\": 25})\nprint(record.proptypes) # Returns property type definitions\n```\n\n### label\n\nGets the record's label.\n\n**Type:** `str`\n\n**Example:**\n\n```python\nrecord = db.records.create(\"USER\", {\"name\": \"John\"})\nprint(record.label) # \"USER\"\n```\n\n### timestamp\n\nGets the record's creation timestamp from its ID.\n\n**Type:** `int`\n\n**Example:**\n\n```python\nrecord = db.records.create(\"USER\", {\"name\": \"John\"})\nprint(record.timestamp) # Unix timestamp in milliseconds\n```\n\n### date\n\nGets the record's creation date.\n\n**Type:** `datetime`\n\n**Example:**\n\n```python\nrecord = db.records.create(\"USER\", {\"name\": \"John\"})\nprint(record.date) # datetime object\n```\n\n## Methods\n\n### set()\n\nUpdates all data for the record.\n\n**Signature:**\n\n```python\ndef set(\n self,\n data: Dict[str, Any],\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `data` (Dict[str, Any]): New record data\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\nrecord = db.records.create(\"USER\", {\"name\": \"John\"})\nresponse = record.set({\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\",\n \"age\": 30\n})\n```\n\n### update()\n\nUpdates specific fields of the record.\n\n**Signature:**\n\n```python\ndef update(\n self,\n data: Dict[str, Any],\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `data` (Dict[str, Any]): Partial record data to update\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\nrecord = db.records.create(\"USER\", {\n \"name\": \"John\",\n \"email\": \"john@example.com\"\n})\nresponse = record.update({\n \"email\": \"john.doe@example.com\"\n})\n```\n\n### attach()\n\nCreates relationships with other records.\n\n**Signature:**\n\n```python\ndef attach(\n self,\n target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], \"Record\", List[\"Record\"]],\n options: Optional[RelationshipOptions] = None,\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `target` (Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]]): Target record(s)\n- `options` (Optional[RelationshipOptions]): Relationship options\n - `direction` (Optional[Literal[\"in\", \"out\"]]): Relationship direction\n - `type` (Optional[str]): Relationship type\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\n# Create two records\nuser = db.records.create(\"USER\", {\"name\": \"John\"})\ngroup = db.records.create(\"GROUP\", {\"name\": \"Admins\"})\n\n# Attach user to group\nresponse = user.attach(\n target=group,\n options=RelationshipOptions(\n type=\"BELONGS_TO\",\n direction=\"out\"\n )\n)\n```\n\n### detach()\n\nRemoves relationships with other records.\n\n**Signature:**\n\n```python\ndef detach(\n self,\n target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], \"Record\", List[\"Record\"]],\n options: Optional[RelationshipDetachOptions] = None,\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `target` (Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], Record, List[Record]]): Target record(s)\n- `options` (Optional[RelationshipDetachOptions]): Detach options\n - `direction` (Optional[Literal[\"in\", \"out\"]]): Relationship direction\n - `typeOrTypes` (Optional[Union[str, List[str]]]): Relationship type(s)\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\n# Detach user from group\nresponse = user.detach(\n target=group,\n options=RelationshipDetachOptions(\n typeOrTypes=\"BELONGS_TO\",\n direction=\"out\"\n )\n)\n```\n\n### delete()\n\nDeletes the record.\n\n**Signature:**\n\n```python\ndef delete(\n self,\n transaction: Optional[Transaction] = None\n) -> Dict[str, str]\n```\n\n**Arguments:**\n\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, str]`: Response data\n\n**Example:**\n\n```python\nuser = db.records.create(\"USER\", {\"name\": \"John\"})\nresponse = user.delete()\n```\n\n## Complete Usage Example\n\nHere's a comprehensive example demonstrating various Record operations:\n\n```python\n# Create a new record\nuser = db.records.create(\"USER\", {\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\",\n \"age\": 30\n})\n\n# Access properties\nprint(f\"Record ID: {user.id}\")\nprint(f\"Label: {user.label}\")\nprint(f\"Created at: {user.date}\")\n\n# Update record data\nuser.update({\n \"age\": 31,\n \"title\": \"Senior Developer\"\n})\n\n# Create related records\ndepartment = db.records.create(\"DEPARTMENT\", {\n \"name\": \"Engineering\"\n})\n\nproject = db.records.create(\"PROJECT\", {\n \"name\": \"Secret Project\"\n})\n\n# Create relationships\nuser.attach(\n target=department,\n options=RelationshipOptions(\n type=\"BELONGS_TO\",\n direction=\"out\"\n )\n)\n\nuser.attach(\n target=project,\n options=RelationshipOptions(\n type=\"WORKS_ON\",\n direction=\"out\"\n )\n)\n\n# Remove relationship\nuser.detach(\n target=project,\n options=RelationshipDetachOptions(\n typeOrTypes=\"WORKS_ON\",\n direction=\"out\"\n )\n)\n\n# Delete record\nuser.delete()\n```\n\n## Working with Transactions\n\nRecords can be manipulated within transactions for atomic operations:\n\n```python\n# Start a transaction\ntransaction = db.transactions.begin()\ntry:\n # Create user\n user = db.records.create(\n \"USER\",\n {\"name\": \"John Doe\"},\n transaction=transaction\n )\n\n # Update user\n user.update(\n {\"status\": \"active\"},\n transaction=transaction\n )\n\n # Create and attach department\n dept = db.records.create(\n \"DEPARTMENT\",\n {\"name\": \"Engineering\"},\n transaction=transaction\n )\n\n user.attach(\n target=dept,\n options=RelationshipOptions(type=\"BELONGS_TO\"),\n transaction=transaction\n )\n\n # Explicitly commit the transaction to make changes permanent\n transaction.commit()\nexcept Exception as e:\n # Rollback if any error occurs\n transaction.rollback()\n raise e\n\n# Alternative: Using context manager\nwith db.transactions.begin() as transaction:\n # Perform operations...\n user = db.records.create(\n \"USER\",\n {\"name\": \"John Doe\"},\n transaction=transaction\n )\n\n # Must explicitly commit - transactions are NOT automatically committed\n transaction.commit()\n```\n\n---\n\n# PropertiesAPI Documentation\n\nThe `PropertiesAPI` class provides methods for managing and querying properties in RushDB.\n\n## Class Definition\n\n```python\nclass PropertiesAPI(BaseAPI):\n```\n\n## Methods\n\n### find()\n\nRetrieves a list of properties based on optional search criteria.\n\n**Signature:**\n\n```python\ndef find(\n self,\n search_query: Optional[SearchQuery] = None,\n transaction: Optional[Transaction] = None\n) -> List[Property]\n```\n\n**Arguments:**\n\n- `query` (Optional[SearchQuery]): Search query parameters for filtering properties\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `List[Property]`: List of properties matching the search criteria\n\n**Example:**\n\n```python\n# Find all properties\nproperties = db.properties.find()\n\n# Find properties with specific criteria\nquery = {\n \"where\": {\n \"name\": {\"$startsWith\": \"user_\"}, # Properties starting with 'user_'\n \"type\": \"string\" # Only string type properties\n },\n \"limit\": 10 # Limit to 10 results\n}\nfiltered_properties = db.properties.find(query)\n```\n\n### find_by_id()\n\nRetrieves a specific property by its ID.\n\n**Signature:**\n\n```python\ndef find_by_id(\n self,\n property_id: str,\n transaction: Optional[Transaction] = None\n) -> Property\n```\n\n**Arguments:**\n\n- `property_id` (str): Unique identifier of the property\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Property`: Property details\n\n**Example:**\n\n```python\n# Retrieve a specific property by ID\nproperty_details = db.properties.find_by_id(\"prop_123456\")\n```\n\n### delete()\n\nDeletes a property by its ID.\n\n**Signature:**\n\n```python\ndef delete(\n self,\n property_id: str,\n transaction: Optional[Transaction] = None\n) -> None\n```\n\n**Arguments:**\n\n- `property_id` (str): Unique identifier of the property to delete\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `None`\n\n**Example:**\n\n```python\n# Delete a property\ndb.properties.delete(\"prop_123456\")\n```\n\n### values()\n\nRetrieves values for a specific property with optional sorting and pagination.\n\n**Signature:**\n\n```python\ndef values(\n self,\n property_id: str,\n sort: Optional[Literal[\"asc\", \"desc\"]] = None,\n skip: Optional[int] = None,\n limit: Optional[int] = None,\n transaction: Optional[Transaction] = None\n) -> PropertyValuesData\n```\n\n**Arguments:**\n\n- `property_id` (str): Unique identifier of the property\n- `sort` (Optional[Literal[\"asc\", \"desc\"]]): Sort order of values\n- `skip` (Optional[int]): Number of values to skip (for pagination)\n- `limit` (Optional[int]): Maximum number of values to return\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `PropertyValuesData`: Property values data, including optional min/max and list of values\n\n**Example:**\n\n```python\n# Get property values\nvalues_data = db.properties.values(\n property_id=\"prop_age\",\n sort=\"desc\", # Sort values in descending order\n skip=0, # Start from the first value\n limit=100 # Return up to 100 values\n)\n\n# Access values\nprint(values_data.get('values', [])) # List of property values\nprint(values_data.get('min')) # Minimum value (for numeric properties)\nprint(values_data.get('max')) # Maximum value (for numeric properties)\n```\n\n## Comprehensive Usage Example\n\n```python\n# Find all properties\nall_properties = db.properties.find()\nfor prop in all_properties:\n print(f\"Property ID: {prop['id']}\")\n print(f\"Name: {prop['name']}\")\n print(f\"Type: {prop['type']}\")\n print(f\"Metadata: {prop.get('metadata', 'No metadata')}\")\n print(\"---\")\n\n# Detailed property search\nquery = {\n \"where\": {\n \"type\": \"number\", # Only numeric properties\n \"name\": {\"$contains\": \"score\"} # Properties with 'score' in name\n },\n \"limit\": 5 # Limit to 5 results\n}\nnumeric_score_properties = db.properties.find(query)\n\n# Get values for a specific property\nif numeric_score_properties:\n first_prop = numeric_score_properties[0]\n prop_values = db.properties.values(\n property_id=first_prop['id'],\n sort=\"desc\",\n limit=50\n )\n print(f\"Values for {first_prop['name']}:\")\n print(f\"Min: {prop_values.get('min')}\")\n print(f\"Max: {prop_values.get('max')}\")\n\n # Detailed property examination\n detailed_prop = db.properties.find_by_id(first_prop['id'])\n print(\"Detailed Property Info:\", detailed_prop)\n```\n\n## Property Types and Structures\n\nRushDB supports the following property types:\n\n- `\"boolean\"`: True/False values\n- `\"datetime\"`: Date and time values\n- `\"null\"`: Null/empty values\n- `\"number\"`: Numeric values\n- `\"string\"`: Text values\n\n### Property Structure Example\n\n```python\nproperty = {\n \"id\": \"prop_unique_id\",\n \"name\": \"user_score\",\n \"type\": \"number\",\n \"metadata\": Optional[str] # Optional additional information\n}\n\nproperty_with_value = {\n \"id\": \"prop_unique_id\",\n \"name\": \"user_score\",\n \"type\": \"number\",\n \"value\": 95.5 # Actual property value\n}\n```\n\n## Transactions\n\nProperties API methods support optional transactions for atomic operations:\n\n```python\n# Using a transaction with explicit commit\ntransaction = db.transactions.begin()\ntry:\n # Perform multiple property-related operations\n property_to_delete = db.properties.find(\n {\"where\": {\"name\": \"temp_property\"}},\n transaction=transaction\n )[0]\n\n db.properties.delete(\n property_id=property_to_delete['id'],\n transaction=transaction\n )\n\n # Explicitly commit the transaction\n transaction.commit()\nexcept Exception as e:\n # Rollback if any error occurs\n transaction.rollback()\n raise e\n\n# Alternative: Using context manager (auto-rollback on error)\nwith db.transactions.begin() as transaction:\n # Perform operations\n property_to_delete = db.properties.find(\n {\"where\": {\"name\": \"temp_property\"}},\n transaction=transaction\n )[0]\n\n db.properties.delete(\n property_id=property_to_delete['id'],\n transaction=transaction\n )\n\n # Must explicitly commit - transactions are NOT automatically committed\n transaction.commit()\n```\n\n## Error Handling\n\nWhen working with the PropertiesAPI, be prepared to handle potential errors:\n\n```python\ntry:\n # Attempt to find or delete a property\n property_details = db.properties.find_by_id(\"non_existent_prop\")\nexcept RushDBError as e:\n print(f\"Error: {e}\")\n print(f\"Error Details: {e.details}\")\n```\n\n---\n\n# LabelsAPI Documentation\n\nThe `LabelsAPI` class provides methods for discovering and working with record labels in RushDB. Labels are used to categorize and type records, similar to table names in relational databases.\n\n## Class Definition\n\n```python\nclass LabelsAPI(BaseAPI):\n```\n\n## Methods\n\n### find()\n\nDiscovers labels (record types) that exist in the database and can optionally filter them based on search criteria.\n\n**Signature:**\n\n```python\ndef find(\n self,\n search_query: Optional[SearchQuery] = None,\n transaction: Optional[Transaction] = None\n) -> Dict[str, int]\n```\n\n**Arguments:**\n\n- `search_query` (Optional[SearchQuery]): Search criteria to filter labels\n- `transaction` (Optional[Transaction]): Optional transaction object\n\n**Returns:**\n\n- `Dict[str, int]`: Dictionary mapping label names to their record counts\n\n**Example:**\n\n```python\n# Get all labels in the database\nall_labels = db.labels.find()\nprint(\"Available labels:\", all_labels)\n# Output: {'USER': 150, 'DEPARTMENT': 12, 'PROJECT': 45, 'COMPANY': 3}\n\n# Search for labels amongst records matching a pattern\nfrom rushdb.models.search_query import SearchQuery\nquery = SearchQuery(where={\"name\": {\"$contains\": \"alice\"}})\nuser_labels = db.labels.find(query)\nprint(\"Labels for records containing 'alice':\", user_labels)\n# Output: {'USER': 2, 'EMPLOYEE': 1}\n```\n\n## Complete Usage Example\n\n```python\n# Discover all record types in the database\nall_labels = db.labels.find()\nprint(f\"Database contains {len(all_labels)} record types:\")\nfor label, count in all_labels.items():\n print(f\" - {label}: {count} records\")\n\n# Find labels for records with specific criteria\nquery = SearchQuery(where={\n \"status\": \"active\",\n \"created_date\": {\"$gte\": \"2023-01-01\"}\n})\nactive_labels = db.labels.find(query)\nprint(\"Labels for active records:\")\nfor label, count in active_labels.items():\n print(f\" - {label}: {count} active records\")\n\n# Use with transaction\ntransaction = db.transactions.begin()\ntry:\n labels_in_tx = db.labels.find(transaction=transaction)\n # Process labels...\n transaction.commit()\nexcept Exception as e:\n transaction.rollback()\n raise e\n```\n\n---\n\n# RelationshipsAPI Documentation\n\nThe `RelationshipsAPI` class provides functionality for querying and analyzing relationships between records in RushDB. Relationships represent connections or associations between different records.\n\n## Class Definition\n\n```python\nclass RelationshipsAPI(BaseAPI):\n```\n\n## Methods\n\n### find()\n\nSearch for and retrieve relationships matching the specified criteria with support for pagination and transactions.\n\n**Signature:**\n\n```python\nasync def find(\n self,\n search_query: Optional[SearchQuery] = None,\n pagination: Optional[PaginationParams] = None,\n transaction: Optional[Union[Transaction, str]] = None\n) -> List[Relationship]\n```\n\n**Arguments:**\n\n- `search_query` (Optional[SearchQuery]): Search criteria to filter relationships\n- `pagination` (Optional[PaginationParams]): Pagination options with `limit` and `skip`\n- `transaction` (Optional[Union[Transaction, str]]): Optional transaction object or ID\n\n**Returns:**\n\n- `List[Relationship]`: List of relationships matching the search criteria\n\n**Example:**\n\n```python\nimport asyncio\nfrom rushdb.models.search_query import SearchQuery\n\nasync def main():\n # Find all relationships\n all_relationships = await db.relationships.find()\n print(f\"Total relationships: {len(all_relationships)}\")\n\n # Find relationships with pagination\n pagination = {\"limit\": 50, \"skip\": 0}\n first_page = await db.relationships.find(pagination=pagination)\n\n # Find specific relationship types\n query = SearchQuery(where={\"type\": \"BELONGS_TO\"})\n belongs_to_rels = await db.relationships.find(search_query=query)\n\n # Find relationships involving specific records\n user_query = SearchQuery(where={\n \"$or\": [\n {\"source_id\": \"user-123\"},\n {\"target_id\": \"user-123\"}\n ]\n })\n user_relationships = await db.relationships.find(search_query=user_query)\n\n# Run the async function\nasyncio.run(main())\n```\n\n## PaginationParams\n\nThe `PaginationParams` TypedDict defines pagination options:\n\n```python\nclass PaginationParams(TypedDict, total=False):\n limit: int # Maximum number of relationships to return\n skip: int # Number of relationships to skip\n```\n\n## Complete Usage Example\n\n```python\nimport asyncio\nfrom rushdb.models.search_query import SearchQuery\n\nasync def explore_relationships():\n # Get overview of all relationships\n all_rels = await db.relationships.find()\n print(f\"Database contains {len(all_rels)} relationships\")\n\n # Paginate through relationships\n page_size = 25\n page = 0\n\n while True:\n pagination = {\"limit\": page_size, \"skip\": page * page_size}\n relationships = await db.relationships.find(pagination=pagination)\n\n if not relationships:\n break\n\n print(f\"Page {page + 1}: {len(relationships)} relationships\")\n for rel in relationships:\n print(f\" {rel['source_id']} --[{rel['type']}]--> {rel['target_id']}\")\n\n page += 1\n if len(relationships) < page_size:\n break\n\n # Find relationships by type\n query = SearchQuery(where={\"type\": \"WORKS_ON\"})\n work_relationships = await db.relationships.find(search_query=query)\n print(f\"Found {len(work_relationships)} 'WORKS_ON' relationships\")\n\n # Find relationships within a transaction\n transaction = db.transactions.begin()\n try:\n tx_rels = await db.relationships.find(transaction=transaction)\n # Process relationships...\n transaction.commit()\n except Exception as e:\n transaction.rollback()\n raise e\n\n# Run the example\nasyncio.run(explore_relationships())\n```\n\n## Working with Transactions\n\nBoth LabelsAPI and RelationshipsAPI support transactions:\n\n```python\nimport asyncio\n\nasync def transaction_example():\n transaction = db.transactions.begin()\n try:\n # Find labels within transaction\n labels = db.labels.find(transaction=transaction)\n\n # Find relationships within transaction\n relationships = await db.relationships.find(transaction=transaction)\n\n # Perform operations based on discovered data...\n\n # Explicitly commit the transaction\n transaction.commit()\n except Exception as e:\n # Rollback on any error\n transaction.rollback()\n raise e\n\nasyncio.run(transaction_example())\n```\n\n**Note:** The RelationshipsAPI methods are async and require the use of `await` and `asyncio` for proper execution.\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "RushDB Python SDK",
"version": "1.10.0",
"project_urls": {
"Documentation": "https://docs.rushdb.com",
"Homepage": "https://github.com/rush-db/rushdb-python",
"Repository": "https://github.com/rush-db/rushdb-python"
},
"split_keywords": [
"ai",
" ai database",
" app backend",
" app-backend",
" artificial intelligence",
" cloud",
" cypher",
" data analysis",
" data engineering",
" data management",
" data pipeline",
" data science",
" data-analysis",
" data-engineering",
" data-management",
" data-pipeline",
" data-science",
" database",
" db",
" embedding",
" embeddings",
" etl",
" fractal api",
" fractal-api",
" graph",
" graph database",
" graph-database",
" graphs",
" instant database",
" instant db",
" instant-database",
" instant-db",
" json normalization",
" json-normalization",
" machine learning",
" machine-learning",
" modern apps",
" modern-apps",
" neo4j",
" no-schema",
" persistence",
" rag",
" relationships",
" rest api",
" rest-api",
" retrieval augmented generation",
" rush db",
" rush-db",
" rushdb",
" schema-less",
" schemaless",
" self-hosted",
" similarity search",
" vector search",
" vector-search",
" web development",
" web-development"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "1ee7d9791df4913a4a04c78d07122647515d6f7d856b9642741357fcd9c2d529",
"md5": "91cbe4268fb4fe06047402402ada0ed0",
"sha256": "672faa5d26a5e3a11177af2d56f4759c5c403a5637b88143e426418b873cf607"
},
"downloads": -1,
"filename": "rushdb-1.10.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "91cbe4268fb4fe06047402402ada0ed0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 37647,
"upload_time": "2025-07-27T12:13:15",
"upload_time_iso_8601": "2025-07-27T12:13:15.441254Z",
"url": "https://files.pythonhosted.org/packages/1e/e7/d9791df4913a4a04c78d07122647515d6f7d856b9642741357fcd9c2d529/rushdb-1.10.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "7e60df02679210dba505bd595e800a1d0edc04d6a13906bacc3a51937b17a037",
"md5": "4d6d491edb2f87915ec446fa0619d483",
"sha256": "06f7935c38bce154970ff90920cec375ac7a6b7b0f2962b3285fccf1cb4136e3"
},
"downloads": -1,
"filename": "rushdb-1.10.0.tar.gz",
"has_sig": false,
"md5_digest": "4d6d491edb2f87915ec446fa0619d483",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 95579,
"upload_time": "2025-07-27T12:13:16",
"upload_time_iso_8601": "2025-07-27T12:13:16.781668Z",
"url": "https://files.pythonhosted.org/packages/7e/60/df02679210dba505bd595e800a1d0edc04d6a13906bacc3a51937b17a037/rushdb-1.10.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-27 12:13:16",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "rush-db",
"github_project": "rushdb-python",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "rushdb"
}