{"id":24914103,"url":"https://github.com/rush-db/rushdb-python","last_synced_at":"2025-08-09T06:06:13.501Z","repository":{"id":275278438,"uuid":"922425462","full_name":"rush-db/rushdb-python","owner":"rush-db","description":"RushDB Python SDK","archived":false,"fork":false,"pushed_at":"2025-02-14T18:32:35.000Z","size":86,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-14T19:30:53.235Z","etag":null,"topics":["data-engineering","data-science","database","etl","graphdatabase","machine-learning","neo4j","python","rag"],"latest_commit_sha":null,"homepage":"https://rushdb.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rush-db.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-26T06:55:20.000Z","updated_at":"2025-02-14T18:31:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"593bbba3-290d-45bf-bd74-b927f3da19a2","html_url":"https://github.com/rush-db/rushdb-python","commit_stats":null,"previous_names":["rush-db/rushdb-python"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rush-db%2Frushdb-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rush-db%2Frushdb-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rush-db%2Frushdb-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rush-db%2Frushdb-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rush-db","download_url":"https://codeload.github.com/rush-db/rushdb-python/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245974195,"owners_count":20702982,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-engineering","data-science","database","etl","graphdatabase","machine-learning","neo4j","python","rag"],"created_at":"2025-02-02T06:16:26.357Z","updated_at":"2025-08-09T06:06:13.479Z","avatar_url":"https://github.com/rush-db.png","language":"Python","readme":"\u003cdiv align=\"center\"\u003e\n\n![RushDB Logo](https://raw.githubusercontent.com/rush-db/rushdb/main/rushdb-logo.svg)\n\n# RushDB Python SDK\n\n![PyPI - Version](https://img.shields.io/pypi/v/rushdb)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/rushdb)\n![PyPI - License](https://img.shields.io/pypi/l/rushdb)\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[📖 Documentation](https://docs.rushdb.com/python-sdk/introduction) • [🌐 Website](https://rushdb.com) • [☁️ Cloud Platform](https://app.rushdb.com)\n\n\u003c/div\u003e\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 \u0026 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\u003e **Implementation Notes:**\n\u003e\n\u003e - If `search_query` is not provided during initialization, it defaults to an empty dictionary `{}`\n\u003e - The `has_more` property is calculated by comparing total with loaded records\n\u003e - The `__bool__` method returns `True` if the result contains any items (`len(data) \u003e 0`)\n\u003e - `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\u003cdiv align=\"center\"\u003e\n  \u003cp\u003e\n    \u003ca href=\"https://docs.rushdb.com/python-sdk/introduction\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/Full_Documentation-docs.rushdb.com-6D28D9?style=for-the-badge\" alt=\"View Documentation\" /\u003e\n    \u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\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) -\u003e 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) -\u003e 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) -\u003e 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) \u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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) -\u003e 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']}]--\u003e {rel['target_id']}\")\n\n        page += 1\n        if len(relationships) \u003c 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","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frush-db%2Frushdb-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frush-db%2Frushdb-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frush-db%2Frushdb-python/lists"}