Organizing with Tags and Collections
Organizing bookmarks in etchblok-test-api is handled through the BookmarkService, which provides a unified interface for managing tags and collections. The service ensures data integrity by handling cross-entity operations, such as cleaning up tag references when a tag is deleted.
Categorizing with Tags
Tags in etchblok-test-api are labels with a name and a preset color. You use the BookmarkService.create_tag method to define new tags and the update_bookmark method to associate them with specific bookmarks.
Creating and Updating Tags
When creating a tag, you can specify a color from the TagColor enum defined in app.models.tag.
from app.services.bookmark_service import BookmarkService
from app.models.tag import TagColor
service = BookmarkService()
# Create a new tag
tag_data = {
"name": "Research",
"color": TagColor.BLUE.value,
"description": "Academic and technical papers"
}
tag, error = service.create_tag(tag_data)
if tag:
print(f"Created tag: {tag.name} with ID: {tag.id}")
Attaching Tags to Bookmarks
To attach a tag to a bookmark, pass the tag's ID in the tags list when creating or updating a bookmark via the BookmarkService.
# Update a bookmark to include the new tag
bookmark_id = "abc12345"
update_data = {
"tags": [tag.id]
}
updated_bookmark, error = service.update_bookmark(bookmark_id, update_data)
Automated Tag Cleanup
One of the primary responsibilities of the BookmarkService is maintaining referential integrity. When you delete a tag using delete_tag, the service automatically:
- Identifies all bookmarks currently using that tag.
- Strips the tag ID from those bookmarks.
- Persists the updated bookmarks to the repository.
- Invalidates the cache for every affected bookmark.
This logic is implemented in app.services.bookmark_service.BookmarkService.delete_tag:
def delete_tag(self, tag_id: str) -> bool:
"""Delete a tag and strip it from all bookmarks."""
tag = self._repo.get_tag(tag_id)
if not tag:
return False
# Automated cleanup across bookmarks
for bookmark in self._repo.get_bookmarks_with_tag(tag_id):
bookmark.remove_tag(tag_id)
self._repo.save_bookmark(bookmark)
self._cache.invalidate(bookmark.id)
self._repo.delete_tag(tag_id)
return True
Grouping with Collections
Collections allow you to group bookmarks either manually or dynamically using smart filters.
Manual Collections
Manual collections require you to explicitly add or remove bookmarks using their IDs.
# Create a manual collection
collection_data = {"name": "Work Projects"}
collection, error = service.create_collection(collection_data)
# Add a bookmark to the collection
if collection:
success = service.add_to_collection(collection.id, "bookmark_id_123")
Smart Collections
Smart collections use a filter_rule to automatically group bookmarks. The Collection model in app.models.collection uses the _apply_filter method to match the rule against bookmark titles and descriptions.
# Create a smart collection for Python-related bookmarks
smart_collection_data = {
"name": "Python Resources",
"type": "smart",
"filter_rule": "python"
}
smart_collection, error = service.create_collection(smart_collection_data)
The filtering logic in Collection._apply_filter performs a case-insensitive search:
def _apply_filter(self, bookmarks: list) -> List[str]:
if not self.filter_rule:
return []
keyword = self.filter_rule.lower()
return [b.id for b in bookmarks if keyword in b.title.lower() or keyword in b.description.lower()]
Best Practices and Performance
- Singleton Access: Always access organization features through the
BookmarkServicesingleton. This ensures that cache invalidation (via the internalLRUCache) stays consistent across different parts of the etchblok-test-api application. - Tag Limits: Tag names are validated to be non-empty and under 50 characters. The
BookmarkServicewill return an error message if these constraints are violated. - Deletion Impact: Be aware that deleting a widely-used tag triggers a loop that updates every associated bookmark. In etchblok-test-api, this includes repository writes and cache invalidations for each item, which may impact performance if the tag is attached to thousands of bookmarks.