Skip to content

Commit

Permalink
feat(main.py): Non-paginated get_nodes /nodes/fast
Browse files Browse the repository at this point in the history
This is non-paginated version of get_nodes query,
that solves performance/latency issues on some queries.

Signed-off-by: Denys Fedoryshchenko <denys.f@collabora.com>
  • Loading branch information
nuclearcat committed Oct 30, 2024
1 parent 3d6c00a commit 1c2dc13
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
27 changes: 27 additions & 0 deletions api/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,33 @@ async def find_by_attributes(self, model, attributes):
query = self._prepare_query(attributes)
return await paginate(collection=col, query_filter=query)

async def find_by_attributes_nonpaginated(self, model, attributes):
"""Find objects with matching attributes
Find all objects with attributes matching the key/value pairs in the
attributes dictionary using pagination and return the paginated
response.
The response dictionary will include 'items', 'total', 'limit',
and 'offset' keys.
"""
col = self._get_collection(model)
query = self._prepare_query(attributes)
# find "limit" and "offset" keys in the query, retrieve them and
# remove them from the query
limit = query.pop('limit', None)
offset = query.pop('offset', None)
# convert to int if limit and offset are strings
limit = int(limit) if limit is not None else None
offset = int(offset) if offset is not None else None
if limit is not None and offset is not None:
return await (col.find(query)
.skip(offset).limit(limit).to_list(None))
if limit is not None:
return await col.find(query).limit(limit).to_list(None)
if offset is not None:
return await col.find(query).skip(offset).to_list(None)
return await col.find(query).to_list(None)

async def count(self, model, attributes):
"""Count objects with matching attributes
Expand Down
26 changes: 26 additions & 0 deletions api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,32 @@ async def get_nodes(request: Request):
add_pagination(app)


@app.get('/nodes/fast', response_model=List[Node])
async def get_nodes_fast(request: Request):
"""Get all the nodes if no request parameters have passed.
This is non-paginated version of get_nodes.
Still options limit=NNN and offset=NNN works and forwarded
as limit and skip to the MongoDB.
"""
query_params = dict(request.query_params)

query_params = await translate_null_query_params(query_params)

try:
# Query using the base Node model, regardless of the specific
# node type
model = Node
translated_params = model.translate_fields(query_params)
resp = await db.find_by_attributes_nonpaginated(model,
translated_params)
return resp
except KeyError as error:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Node not found with the kind: {str(error)}"
) from error


@app.get('/count', response_model=int)
async def get_nodes_count(request: Request):
"""Get the count of all the nodes if no request parameters have passed.
Expand Down

0 comments on commit 1c2dc13

Please sign in to comment.