From cf473ce003f355ed2dae49f3bfa97da24862c736 Mon Sep 17 00:00:00 2001 From: Artemiy Vereshchinskiy Date: Mon, 30 Jun 2025 09:35:42 +0700 Subject: [PATCH 1/2] Update labels api and keywords --- README.md | 295 ++++++++++++++++++++++++++++++++++++++- pyproject.toml | 50 +++++-- src/rushdb/api/labels.py | 2 +- 3 files changed, 329 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index e3d2f84..2e35a35 100644 --- a/README.md +++ b/README.md @@ -1017,7 +1017,8 @@ Records can be manipulated within transactions for atomic operations: ```python # Start a transaction -with db.transactions.begin() as transaction: +transaction = db.transactions.begin() +try: # Create user user = db.records.create( "USER", @@ -1044,8 +1045,24 @@ with db.transactions.begin() as transaction: transaction=transaction ) - # Transaction will automatically commit if no errors occur - # If an error occurs, it will automatically rollback + # 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() ``` --- @@ -1280,8 +1297,9 @@ property_with_value = { Properties API methods support optional transactions for atomic operations: ```python -# Using a transaction -with db.transactions.begin() as transaction: +# 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"}}, @@ -1292,7 +1310,29 @@ with db.transactions.begin() as transaction: property_id=property_to_delete['id'], transaction=transaction ) - # Transaction will automatically commit if no errors occur + + # 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 @@ -1307,3 +1347,246 @@ 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. diff --git a/pyproject.toml b/pyproject.toml index 57fdb3e..6c1da0d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "rushdb" -version = "1.8.0" +version = "1.9.0" description = "RushDB Python SDK" authors = [ {name = "RushDB Team", email = "hi@rushdb.com"} @@ -11,30 +11,58 @@ requires-python = ">=3.8" keywords = [ "database", "graph database", + "graph-database", "instant database", "instant-database", - "instantdatabase", "instant db", "instant-db", - "instantdb", "neo4j", - "cypher", + "vector search", + "vector-search", + "similarity search", "ai", "ai database", - "etl", - "data-pipeline", + "artificial intelligence", + "machine learning", + "machine-learning", "data science", "data-science", + "rag", + "retrieval augmented generation", + "embedding", + "embeddings", + "json normalization", + "json-normalization", + "schema-less", + "schemaless", + "no-schema", + "modern apps", + "modern-apps", + "web development", + "web-development", + "app backend", + "app-backend", + "etl", + "data pipeline", + "data-pipeline", + "data engineering", + "data-engineering", + "data analysis", + "data-analysis", "data management", "data-management", - "machine learning", - "machine-learning", "persistence", - "db", + "fractal api", + "fractal-api", + "self-hosted", + "cloud", + "rest api", + "rest-api", "graph", "graphs", - "graph-database", - "self-hosted", + "relationships", + "cypher", + "db", "rush-db", "rush db", "rushdb" diff --git a/src/rushdb/api/labels.py b/src/rushdb/api/labels.py index 365fb63..409c0da 100644 --- a/src/rushdb/api/labels.py +++ b/src/rushdb/api/labels.py @@ -43,7 +43,7 @@ def find( self, search_query: Optional[SearchQuery] = None, transaction: Optional[Transaction] = None, - ) -> List[str]: + ) -> Dict[str, int]: """Search for and retrieve labels matching the specified criteria. Discovers labels (record types) that exist in the database and can optionally From eba82ab04518ba403cb205ed9ce2dc45a9ca17d8 Mon Sep 17 00:00:00 2001 From: Artemiy Vereshchinskiy Date: Mon, 30 Jun 2025 09:45:17 +0700 Subject: [PATCH 2/2] Fix import --- src/rushdb/api/labels.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rushdb/api/labels.py b/src/rushdb/api/labels.py index 409c0da..73eda86 100644 --- a/src/rushdb/api/labels.py +++ b/src/rushdb/api/labels.py @@ -1,5 +1,5 @@ import typing -from typing import List, Optional +from typing import Dict, Optional from ..models.search_query import SearchQuery from ..models.transaction import Transaction pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy