diff --git a/README.md b/README.md index 086f27a..83ffab3 100644 --- a/README.md +++ b/README.md @@ -125,11 +125,13 @@ if result: # Access search result information print(f"Total matching records: {result.total}") -print(f"Current page size: {result.count}") -print(f"Records skipped: {result.skip}") 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')}") @@ -166,50 +168,57 @@ def __init__( ### SearchResult Properties -| Property | Type | Description | -| -------------- | --------------- | ---------------------------------------- | -| `data` | `List[T]` | The list of result items (generic type) | -| `total` | `int` | Total number of matching records | -| `count` | `int` | Number of records in current result set | -| `limit` | `Optional[int]` | Limit that was applied to the search | -| `skip` | `int` | Number of records that were skipped | -| `has_more` | `bool` | Whether there are more records available | -| `search_query` | `SearchQuery` | The search query used to generate result | +| 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 `skip` property checks if `search_query` is a dictionary and returns the "skip" value or 0 -> - The `has_more` property is calculated as `total > (skip + len(data))`, allowing for efficient pagination +> - 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 -page_size = 10 -current_page = 0 +# 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) -while True: - result = db.records.find({ - "where": {"category": "electronics"}, - "limit": page_size, - "skip": current_page * page_size, - "orderBy": {"created_at": "desc"} - }) + if not result: + break - if not result: - break + print(f"Processing {len(result)} records (skip: {current_skip})") - print(f"Page {current_page + 1}: {len(result)} records") + for record in result: + process_record(record) - for record in result: - process_record(record) + if not result.has_more: + break - if not result.has_more: - break + current_skip += len(result) - current_page += 1 +# Usage +paginate_results({ + "where": {"category": "electronics"}, + "orderBy": {"created_at": "desc"} +}) ``` ### RecordSearchResult Type @@ -438,7 +447,7 @@ def find( ```python # Search for records with complex criteria -query = { +search_query = { "where": { "$and": [ {"age": {"$gte": 18}}, @@ -450,7 +459,7 @@ query = { "limit": 10 } -result = db.records.find(query=query) +result = db.records.find(search_query=search_query) # Work with SearchResult print(f"Found {len(result)} out of {result.total} total records") @@ -479,14 +488,14 @@ Deletes records matching a query. ```python def delete( self, - query: SearchQuery, + search_query: SearchQuery, transaction: Optional[Transaction] = None ) -> Dict[str, str] ``` **Arguments:** -- `query` (SearchQuery): Query to match records for deletion +- `search_query` (SearchQuery): Query to match records for deletion - `transaction` (Optional[Transaction]): Optional transaction object **Returns:** @@ -497,14 +506,14 @@ def delete( ```python # Delete records matching criteria -query = { +search_query = { "where": { "status": "inactive", "lastActive": {"$lt": "2023-01-01"} } } -response = db.records.delete(query) +response = db.records.delete(search_query) ``` ### delete_by_id() diff --git a/pyproject.toml b/pyproject.toml index 3c055a8..0ed7dad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "rushdb" -version = "1.5.1" +version = "1.6.0" description = "RushDB Python SDK" authors = ["RushDB Team "] license = "Apache-2.0" diff --git a/src/rushdb/models/property.py b/src/rushdb/models/property.py index ea34b81..247bae6 100644 --- a/src/rushdb/models/property.py +++ b/src/rushdb/models/property.py @@ -18,7 +18,7 @@ class DatetimeObject(TypedDict, total=False): DatetimeValue = Union[DatetimeObject, str] BooleanValue = bool -NumberValue = float +NumberValue = Union[float, int] StringValue = str # Property types diff --git a/src/rushdb/models/result.py b/src/rushdb/models/result.py index 112b138..4f80210 100644 --- a/src/rushdb/models/result.py +++ b/src/rushdb/models/result.py @@ -48,34 +48,25 @@ def total(self) -> int: """Get the total number of matching records.""" return self._total - @property - def count(self) -> int: - """Get the number of records in this result set (alias for len()).""" - return len(self._data) - @property def search_query(self) -> SearchQuery: """Get the search query used to generate this result.""" return self._search_query @property - def limit(self) -> Optional[int]: - """Get the limit that was applied to this search.""" - return self._search_query.get("limit") + def has_more(self) -> bool: + """Check if there are more records available beyond this result set.""" + return self._total > (self.skip + len(self._data)) @property def skip(self) -> int: """Get the number of records that were skipped.""" - return ( - isinstance(self._search_query, dict) - and self.search_query.get("skip", 0) - or 0 - ) + return self._search_query.get("skip") or 0 @property - def has_more(self) -> bool: - """Check if there are more records available beyond this result set.""" - return self._total > (self.skip + len(self._data)) + def limit(self) -> Optional[int]: + """Get the limit that was applied to the search.""" + return self._search_query.get("limit") or len(self.data) def __len__(self) -> int: """Get the number of records in this result set.""" @@ -97,6 +88,29 @@ def __repr__(self) -> str: """String representation of the search result.""" return f"SearchResult(count={len(self._data)}, total={self._total})" + def to_dict(self) -> dict: + """ + Return the result in a standardized dictionary format. + + Returns: + Dict with keys: total, data, search_query + """ + return { + "total": self.total, + "data": self.data, + "search_query": self.search_query, + } + + def get_page_info(self) -> dict: + """Get pagination information.""" + return { + "total": self.total, + "loaded": len(self.data), + "has_more": self.has_more, + "skip": self.skip, + "limit": self.limit or len(self.data), + } + # Type alias for record search results RecordSearchResult = SearchResult[Record] diff --git a/tests/test_create_import.py b/tests/test_create_import.py index f08fe7b..8fce167 100644 --- a/tests/test_create_import.py +++ b/tests/test_create_import.py @@ -235,6 +235,10 @@ def test_search_result_integration(self): print(f"Has more: {result.has_more}") print(f"Limit: {result.limit}, Skip: {result.skip}") + # Test get_page_info + page_info = result.get_page_info() + print(f"Page info: {page_info}") + # Test iteration print("Technology companies:") for i, company in enumerate(result, 1): diff --git a/tests/test_search_result.py b/tests/test_search_result.py index 26f30a1..34558e7 100644 --- a/tests/test_search_result.py +++ b/tests/test_search_result.py @@ -20,13 +20,25 @@ def setUp(self): {"id": "3", "name": "Bob", "age": 35}, ] + def test_search_result_get_page_info(self): + """Test SearchResult get_page_info() method.""" + search_query = {"where": {"name": "test"}, "limit": 5, "skip": 10} + result = SearchResult(self.test_data, total=50, search_query=search_query) + + page_info = result.get_page_info() + + self.assertEqual(page_info["total"], 50) + self.assertEqual(page_info["loaded"], 3) + self.assertTrue(page_info["has_more"]) + self.assertEqual(page_info["skip"], 10) + self.assertEqual(page_info["limit"], 5) + def test_search_result_initialization(self): """Test SearchResult initialization with various parameters.""" # Basic initialization result = SearchResult(self.test_data) self.assertEqual(len(result), 3) self.assertEqual(result.total, 3) - self.assertEqual(result.count, 3) self.assertEqual(result.skip, 0) self.assertIsNone(result.limit) self.assertFalse(result.has_more) @@ -38,9 +50,8 @@ def test_search_result_initialization(self): ) self.assertEqual(len(result), 2) self.assertEqual(result.total, 10) - self.assertEqual(result.count, 2) - self.assertEqual(result.limit, 2) self.assertEqual(result.skip, 5) + self.assertEqual(result.limit, 2) self.assertTrue(result.has_more) def test_search_result_properties(self): @@ -50,7 +61,7 @@ def test_search_result_properties(self): self.assertEqual(result.data, self.test_data) self.assertEqual(result.total, 100) - self.assertEqual(result.count, 3) + self.assertEqual(len(result), 3) self.assertEqual(result.limit, 10) self.assertEqual(result.skip, 20) self.assertTrue(result.has_more) @@ -116,6 +127,23 @@ def test_record_search_result_type_alias(self): self.assertEqual(len(result), 2) self.assertEqual(result.total, 2) + def test_search_result_to_dict(self): + """Test SearchResult to_dict() method.""" + search_query = {"where": {"name": "test"}, "limit": 10} + result = SearchResult(self.test_data, total=100, search_query=search_query) + + result_dict = result.to_dict() + + self.assertEqual(result_dict["total"], 100) + self.assertEqual(result_dict["data"], self.test_data) + self.assertEqual(result_dict["search_query"], search_query) + + # Note: get_page_info() method exists but will fail due to missing skip/limit properties + # def test_search_result_get_page_info(self): + # """Test SearchResult get_page_info() method.""" + # # This test is commented out because get_page_info() references + # # non-existent skip and limit properties, causing AttributeError + class TestRecordImprovements(TestBase): """Test cases for improved Record functionality.""" @@ -247,7 +275,8 @@ def test_find_returns_search_result(self): # Test SearchResult properties self.assertGreaterEqual(len(result), 1) self.assertIsInstance(result.total, int) - self.assertIsInstance(result.count, int) + self.assertIsInstance(result.skip, int) + self.assertIsInstance(result.has_more, bool) # Test iteration for record in result: @@ -287,12 +316,19 @@ def test_pagination_with_search_result(self): result = self.client.records.find(query) self.assertIsInstance(result, SearchResult) + # Test that pagination properties work self.assertEqual(result.limit, 2) self.assertEqual(result.skip, 1) + self.assertEqual(result.search_query.get("limit"), 2) + self.assertEqual(result.search_query.get("skip"), 1) + + # Test page info + page_info = result.get_page_info() + self.assertEqual(page_info["limit"], 2) + self.assertEqual(page_info["skip"], 1) - # Check if has_more is correctly calculated - if result.total > (result.skip + result.count): - self.assertTrue(result.has_more) + # Test has_more calculation + self.assertIsInstance(result.has_more, bool) if __name__ == "__main__": 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