diff --git a/api/db.py b/api/db.py index ec1f5355..ddf231d9 100644 --- a/api/db.py +++ b/api/db.py @@ -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 diff --git a/api/main.py b/api/main.py index 762beda7..1dd8df54 100644 --- a/api/main.py +++ b/api/main.py @@ -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.