Skip to content

Commit 3ab8fd4

Browse files
authored
Merge pull request #14 from rush-db/feat/update-lables-api-and-keywords
Update labels api and keywords
2 parents c397a29 + eba82ab commit 3ab8fd4

File tree

3 files changed

+330
-19
lines changed

3 files changed

+330
-19
lines changed

README.md

Lines changed: 289 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,8 @@ Records can be manipulated within transactions for atomic operations:
10171017

10181018
```python
10191019
# Start a transaction
1020-
with db.transactions.begin() as transaction:
1020+
transaction = db.transactions.begin()
1021+
try:
10211022
# Create user
10221023
user = db.records.create(
10231024
"USER",
@@ -1044,8 +1045,24 @@ with db.transactions.begin() as transaction:
10441045
transaction=transaction
10451046
)
10461047

1047-
# Transaction will automatically commit if no errors occur
1048-
# If an error occurs, it will automatically rollback
1048+
# Explicitly commit the transaction to make changes permanent
1049+
transaction.commit()
1050+
except Exception as e:
1051+
# Rollback if any error occurs
1052+
transaction.rollback()
1053+
raise e
1054+
1055+
# Alternative: Using context manager
1056+
with db.transactions.begin() as transaction:
1057+
# Perform operations...
1058+
user = db.records.create(
1059+
"USER",
1060+
{"name": "John Doe"},
1061+
transaction=transaction
1062+
)
1063+
1064+
# Must explicitly commit - transactions are NOT automatically committed
1065+
transaction.commit()
10491066
```
10501067

10511068
---
@@ -1280,8 +1297,9 @@ property_with_value = {
12801297
Properties API methods support optional transactions for atomic operations:
12811298

12821299
```python
1283-
# Using a transaction
1284-
with db.transactions.begin() as transaction:
1300+
# Using a transaction with explicit commit
1301+
transaction = db.transactions.begin()
1302+
try:
12851303
# Perform multiple property-related operations
12861304
property_to_delete = db.properties.find(
12871305
{"where": {"name": "temp_property"}},
@@ -1292,7 +1310,29 @@ with db.transactions.begin() as transaction:
12921310
property_id=property_to_delete['id'],
12931311
transaction=transaction
12941312
)
1295-
# Transaction will automatically commit if no errors occur
1313+
1314+
# Explicitly commit the transaction
1315+
transaction.commit()
1316+
except Exception as e:
1317+
# Rollback if any error occurs
1318+
transaction.rollback()
1319+
raise e
1320+
1321+
# Alternative: Using context manager (auto-rollback on error)
1322+
with db.transactions.begin() as transaction:
1323+
# Perform operations
1324+
property_to_delete = db.properties.find(
1325+
{"where": {"name": "temp_property"}},
1326+
transaction=transaction
1327+
)[0]
1328+
1329+
db.properties.delete(
1330+
property_id=property_to_delete['id'],
1331+
transaction=transaction
1332+
)
1333+
1334+
# Must explicitly commit - transactions are NOT automatically committed
1335+
transaction.commit()
12961336
```
12971337

12981338
## Error Handling
@@ -1307,3 +1347,246 @@ except RushDBError as e:
13071347
print(f"Error: {e}")
13081348
print(f"Error Details: {e.details}")
13091349
```
1350+
1351+
---
1352+
1353+
# LabelsAPI Documentation
1354+
1355+
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.
1356+
1357+
## Class Definition
1358+
1359+
```python
1360+
class LabelsAPI(BaseAPI):
1361+
```
1362+
1363+
## Methods
1364+
1365+
### find()
1366+
1367+
Discovers labels (record types) that exist in the database and can optionally filter them based on search criteria.
1368+
1369+
**Signature:**
1370+
1371+
```python
1372+
def find(
1373+
self,
1374+
search_query: Optional[SearchQuery] = None,
1375+
transaction: Optional[Transaction] = None
1376+
) -> Dict[str, int]
1377+
```
1378+
1379+
**Arguments:**
1380+
1381+
- `search_query` (Optional[SearchQuery]): Search criteria to filter labels
1382+
- `transaction` (Optional[Transaction]): Optional transaction object
1383+
1384+
**Returns:**
1385+
1386+
- `Dict[str, int]`: Dictionary mapping label names to their record counts
1387+
1388+
**Example:**
1389+
1390+
```python
1391+
# Get all labels in the database
1392+
all_labels = db.labels.find()
1393+
print("Available labels:", all_labels)
1394+
# Output: {'USER': 150, 'DEPARTMENT': 12, 'PROJECT': 45, 'COMPANY': 3}
1395+
1396+
# Search for labels amongst records matching a pattern
1397+
from rushdb.models.search_query import SearchQuery
1398+
query = SearchQuery(where={"name": {"$contains": "alice"}})
1399+
user_labels = db.labels.find(query)
1400+
print("Labels for records containing 'alice':", user_labels)
1401+
# Output: {'USER': 2, 'EMPLOYEE': 1}
1402+
```
1403+
1404+
## Complete Usage Example
1405+
1406+
```python
1407+
# Discover all record types in the database
1408+
all_labels = db.labels.find()
1409+
print(f"Database contains {len(all_labels)} record types:")
1410+
for label, count in all_labels.items():
1411+
print(f" - {label}: {count} records")
1412+
1413+
# Find labels for records with specific criteria
1414+
query = SearchQuery(where={
1415+
"status": "active",
1416+
"created_date": {"$gte": "2023-01-01"}
1417+
})
1418+
active_labels = db.labels.find(query)
1419+
print("Labels for active records:")
1420+
for label, count in active_labels.items():
1421+
print(f" - {label}: {count} active records")
1422+
1423+
# Use with transaction
1424+
transaction = db.transactions.begin()
1425+
try:
1426+
labels_in_tx = db.labels.find(transaction=transaction)
1427+
# Process labels...
1428+
transaction.commit()
1429+
except Exception as e:
1430+
transaction.rollback()
1431+
raise e
1432+
```
1433+
1434+
---
1435+
1436+
# RelationshipsAPI Documentation
1437+
1438+
The `RelationshipsAPI` class provides functionality for querying and analyzing relationships between records in RushDB. Relationships represent connections or associations between different records.
1439+
1440+
## Class Definition
1441+
1442+
```python
1443+
class RelationshipsAPI(BaseAPI):
1444+
```
1445+
1446+
## Methods
1447+
1448+
### find()
1449+
1450+
Search for and retrieve relationships matching the specified criteria with support for pagination and transactions.
1451+
1452+
**Signature:**
1453+
1454+
```python
1455+
async def find(
1456+
self,
1457+
search_query: Optional[SearchQuery] = None,
1458+
pagination: Optional[PaginationParams] = None,
1459+
transaction: Optional[Union[Transaction, str]] = None
1460+
) -> List[Relationship]
1461+
```
1462+
1463+
**Arguments:**
1464+
1465+
- `search_query` (Optional[SearchQuery]): Search criteria to filter relationships
1466+
- `pagination` (Optional[PaginationParams]): Pagination options with `limit` and `skip`
1467+
- `transaction` (Optional[Union[Transaction, str]]): Optional transaction object or ID
1468+
1469+
**Returns:**
1470+
1471+
- `List[Relationship]`: List of relationships matching the search criteria
1472+
1473+
**Example:**
1474+
1475+
```python
1476+
import asyncio
1477+
from rushdb.models.search_query import SearchQuery
1478+
1479+
async def main():
1480+
# Find all relationships
1481+
all_relationships = await db.relationships.find()
1482+
print(f"Total relationships: {len(all_relationships)}")
1483+
1484+
# Find relationships with pagination
1485+
pagination = {"limit": 50, "skip": 0}
1486+
first_page = await db.relationships.find(pagination=pagination)
1487+
1488+
# Find specific relationship types
1489+
query = SearchQuery(where={"type": "BELONGS_TO"})
1490+
belongs_to_rels = await db.relationships.find(search_query=query)
1491+
1492+
# Find relationships involving specific records
1493+
user_query = SearchQuery(where={
1494+
"$or": [
1495+
{"source_id": "user-123"},
1496+
{"target_id": "user-123"}
1497+
]
1498+
})
1499+
user_relationships = await db.relationships.find(search_query=user_query)
1500+
1501+
# Run the async function
1502+
asyncio.run(main())
1503+
```
1504+
1505+
## PaginationParams
1506+
1507+
The `PaginationParams` TypedDict defines pagination options:
1508+
1509+
```python
1510+
class PaginationParams(TypedDict, total=False):
1511+
limit: int # Maximum number of relationships to return
1512+
skip: int # Number of relationships to skip
1513+
```
1514+
1515+
## Complete Usage Example
1516+
1517+
```python
1518+
import asyncio
1519+
from rushdb.models.search_query import SearchQuery
1520+
1521+
async def explore_relationships():
1522+
# Get overview of all relationships
1523+
all_rels = await db.relationships.find()
1524+
print(f"Database contains {len(all_rels)} relationships")
1525+
1526+
# Paginate through relationships
1527+
page_size = 25
1528+
page = 0
1529+
1530+
while True:
1531+
pagination = {"limit": page_size, "skip": page * page_size}
1532+
relationships = await db.relationships.find(pagination=pagination)
1533+
1534+
if not relationships:
1535+
break
1536+
1537+
print(f"Page {page + 1}: {len(relationships)} relationships")
1538+
for rel in relationships:
1539+
print(f" {rel['source_id']} --[{rel['type']}]--> {rel['target_id']}")
1540+
1541+
page += 1
1542+
if len(relationships) < page_size:
1543+
break
1544+
1545+
# Find relationships by type
1546+
query = SearchQuery(where={"type": "WORKS_ON"})
1547+
work_relationships = await db.relationships.find(search_query=query)
1548+
print(f"Found {len(work_relationships)} 'WORKS_ON' relationships")
1549+
1550+
# Find relationships within a transaction
1551+
transaction = db.transactions.begin()
1552+
try:
1553+
tx_rels = await db.relationships.find(transaction=transaction)
1554+
# Process relationships...
1555+
transaction.commit()
1556+
except Exception as e:
1557+
transaction.rollback()
1558+
raise e
1559+
1560+
# Run the example
1561+
asyncio.run(explore_relationships())
1562+
```
1563+
1564+
## Working with Transactions
1565+
1566+
Both LabelsAPI and RelationshipsAPI support transactions:
1567+
1568+
```python
1569+
import asyncio
1570+
1571+
async def transaction_example():
1572+
transaction = db.transactions.begin()
1573+
try:
1574+
# Find labels within transaction
1575+
labels = db.labels.find(transaction=transaction)
1576+
1577+
# Find relationships within transaction
1578+
relationships = await db.relationships.find(transaction=transaction)
1579+
1580+
# Perform operations based on discovered data...
1581+
1582+
# Explicitly commit the transaction
1583+
transaction.commit()
1584+
except Exception as e:
1585+
# Rollback on any error
1586+
transaction.rollback()
1587+
raise e
1588+
1589+
asyncio.run(transaction_example())
1590+
```
1591+
1592+
**Note:** The RelationshipsAPI methods are async and require the use of `await` and `asyncio` for proper execution.

0 commit comments

Comments
 (0)