Implement Generalized Sorting For Entity Search And Get Requests
Introduction
While working on optimizing the germplasm endpoint for the production server, I noticed that the data we returned never had a specified sorting. This led to the data coming back in inconsistent ways, sometimes changing when the same requests were made, in new but unchanged builds with no data changes. Postgres tries to keep some sort of sort going but for some reason it would change. Not good for users who would like these endpoints to be idempotent.
Problem Statement
The current implementation of sorting for entity search and get requests is not robust and does not handle invalid attributes well. This can lead to inconsistent data and errors in the production server. To address this issue, we need to create a generalized sorting implementation that uses reflection to check if the submitted attribute actually exists on the entity.
Existing Implementation
The existing SortBy
class has available values stored as an enum in the class that the values from requests are checked against for the Trials and Studies entities. This type of implementation works fine, but if we want to apply a generalized sort to every entity, the enum would simply be too big and cumbersome to keep track of all the attributes.
Proposed Solution
To create a generalized sorting implementation, we will use reflection to check if the submitted attribute actually exists on the entity. This will involve creating a SortBy
class that can be used for all entities. The class will have a method that takes the entity and the attribute to sort by as input and returns the sorted entities.
Generalized Sorting Implementation
from enum import Enum
from typing import List
class SortOrder(Enum):
ASC = 'asc'
DESC = 'desc'
class SortBy:
def __init__(self, entity):
self.entity = entity
def get_sortable_attributes(self) -> List[str]:
# Get the attributes of the entity
attributes = [attr for attr in dir(self.entity) if not attr.startswith('__')]
# Filter out non-sortable attributes
sortable_attributes = [attr for attr in attributes if hasattr(self.entity, f'get_{attr}')]
return sortable_attributes
def sort(self, attribute: str, order: SortOrder = SortOrder.ASC) -> List:
# Get the sortable attributes of the entity
sortable_attributes = self.get_sortable_attributes()
# Check if the attribute is sortable
if attribute not in sortable_attributes:
raise ValueError(f'Invalid attribute: {attribute}')
# Get the entities
entities = self.entity.get_all()
# Sort the entities
sorted_entities = sorted(entities, key=lambda x: getattr(x, attribute), reverse=(order == SortOrder.DESC))
return sorted_entities
Advertising the New Implementation
To advertise the new implementation to our users, we need to update the Swaggerhub documentation to include the new SortBy
class and its available attributes. We can do this by adding a new section to the documentation that describes the SortBy
class and its usage.
Example Usage
Here is an example of how to use the SortBy
class to sort entities:
# Get the entities
entities = Entity.get_all()
# Create a SortBy instance
sort_by = SortBy(entities)
# Sort the entities by a specific attribute
sorted_entities = sort_by.sort('attribute_name', order=SortOrder.DESC)
# Print the sorted entities
for entity in sorted_entities:
print(entity)
Conclusion
Introduction
In our previous article, we discussed the problem of inconsistent data in the production server due to the lack of a robust sorting implementation. We proposed a solution that uses reflection to check if the submitted attribute actually exists on the entity. We also created a SortBy
class that can be used for all entities and updated the Swaggerhub documentation to include the new implementation. In this article, we will answer some frequently asked questions about the new implementation.
Q: What is the purpose of the SortBy
class?
A: The SortBy
class is a utility class that provides a way to sort entities based on a specific attribute. It uses reflection to check if the submitted attribute actually exists on the entity, ensuring that the sorting is robust and consistent.
Q: How do I use the SortBy
class?
A: To use the SortBy
class, you need to create an instance of it, passing the entity you want to sort as an argument. You can then call the sort
method, passing the attribute you want to sort by and the order (ascending or descending) as arguments.
Q: What happens if I try to sort by an attribute that does not exist on the entity?
A: If you try to sort by an attribute that does not exist on the entity, the SortBy
class will raise a ValueError
. This ensures that the sorting is robust and consistent, and prevents errors from occurring due to invalid attribute names.
Q: Can I sort by multiple attributes?
A: Yes, you can sort by multiple attributes. To do this, you need to create a list of attribute names and pass it to the sort
method. The SortBy
class will then sort the entities based on the first attribute in the list, and then by the second attribute, and so on.
Q: How do I handle pagination when sorting entities?
A: When handling pagination, you need to take into account the sorting of the entities. To do this, you can use the SortBy
class to sort the entities, and then use the limit
and offset
parameters to paginate the results.
Q: Can I use the SortBy
class with other types of data, such as arrays or objects?
A: Yes, you can use the SortBy
class with other types of data, such as arrays or objects. However, you need to ensure that the data is properly formatted and that the attribute names are correct.
Q: How do I update the Swaggerhub documentation to include the new implementation?
A: To update the Swaggerhub documentation, you need to add a new section that describes the SortBy
class and its usage. You can also include examples of how to use the SortBy
class to sort entities.
Q: What are the benefits of using the SortBy
class?
A: The benefits of using the SortBy
class include:
- Robust and consistent sorting of entities
- Easy to use and understand
- Can be used with other types of data, such as arrays or objects
- Can handle pagination and other complex sorting scenarios
Conclusion
In this article, we answered some frequently asked questions about the new implementation of the SortBy
class. We discussed the purpose and usage of the class, as well as its benefits and limitations. We also provided examples of how to use the class to sort entities and update the Swaggerhub documentation. With the SortBy
class, you can ensure that your data is properly sorted and consistent, making it easier to work with and analyze.