From a7c86f1d1eb30e2b76e9dc3ce3af0f5834ea6bfd Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 14 Nov 2023 15:22:12 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(store.py):=20fix=20build=5Ff?= =?UTF-8?q?ilter=5Fconditions=20method=20to=20correctly=20build=20filter?= =?UTF-8?q?=20conditions=20for=20querying=20components=20=E2=9C=A8=20feat(?= =?UTF-8?q?store.py):=20add=20build=5Fliked=5Ffilter=20method=20to=20build?= =?UTF-8?q?=20filter=20conditions=20for=20querying=20liked=20components=20?= =?UTF-8?q?=E2=9C=A8=20feat(store.py):=20add=20build=5Ftags=5Ffilter=20met?= =?UTF-8?q?hod=20to=20build=20filter=20conditions=20for=20querying=20compo?= =?UTF-8?q?nents=20with=20specific=20tags=20=E2=9C=A8=20feat(store.py):=20?= =?UTF-8?q?add=20build=5Ffilter=5Fconditions=20method=20to=20build=20filte?= =?UTF-8?q?r=20conditions=20for=20querying=20components=20with=20various?= =?UTF-8?q?=20filters=20=E2=9C=A8=20feat(store.py):=20modify=20query=5Fcom?= =?UTF-8?q?ponents=20method=20to=20accept=20filter=5Fconditions=20paramete?= =?UTF-8?q?r=20for=20querying=20components=20with=20filters=20=F0=9F=94=A7?= =?UTF-8?q?=20chore(utils.py):=20reorder=20imports=20in=20get=5Ffactories?= =?UTF-8?q?=5Fand=5Fdeps=20function=20=F0=9F=94=A7=20chore(utils.py):=20re?= =?UTF-8?q?order=20imports=20in=20initialize=5Fsession=5Fservice=20functio?= =?UTF-8?q?n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/store.py | 22 +++---- .../langflow/services/store/service.py | 62 +++++++++++-------- src/backend/langflow/services/utils.py | 20 +++--- 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/src/backend/langflow/api/v1/store.py b/src/backend/langflow/api/v1/store.py index 88f7f978f..5133b11f6 100644 --- a/src/backend/langflow/api/v1/store.py +++ b/src/backend/langflow/api/v1/store.py @@ -3,6 +3,7 @@ from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, Query from httpx import HTTPStatusError + from langflow.services.auth import utils as auth_utils from langflow.services.database.models.user.user import User from langflow.services.deps import get_settings_service, get_store_service @@ -86,20 +87,19 @@ def get_components( ): try: with user_data_context(api_key=store_api_Key, store_service=store_service): - filter_conditions: List[Dict[str, Any]] = [] + filter_conditions: List[Dict[str, Any]] = store_service.build_filter_conditions( + search=search, + status=status, + tags=tags, + is_component=is_component, + liked=liked, + api_key=store_api_Key, + ) result: List[ListComponentResponse] = [] authorized = False try: - result, filter_conditions = store_service.query_components( - api_key=store_api_Key, - page=page, - limit=limit, - liked=liked, - is_component=is_component, - search=search, - status=status, - tags=tags, - sort=sort, + result = store_service.query_components( + api_key=store_api_Key, page=page, limit=limit, sort=sort, filter_conditions=filter_conditions ) except HTTPStatusError as exc: if exc.response.status_code == 403: diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index 2c5608311..003c5ac2c 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -4,8 +4,6 @@ from uuid import UUID import httpx from httpx import HTTPError, HTTPStatusError -from loguru import logger - from langflow.services.base import Service from langflow.services.store.schema import ( ComponentResponse, @@ -14,6 +12,7 @@ from langflow.services.store.schema import ( StoreComponentCreate, ) from langflow.services.store.utils import process_tags_for_post +from loguru import logger if TYPE_CHECKING: from langflow.services.settings.service import SettingsService @@ -131,26 +130,15 @@ class StoreService(Service): conditions["_or"].append({"tags": {"tags_id": {"name": {"_icontains": query}}}}) return conditions - def query_components( + def build_filter_conditions( self, - api_key: Optional[str] = None, search: Optional[str] = None, status: Optional[str] = None, tags: Optional[List[str]] = None, - sort: Optional[List[str]] = None, - page: int = 1, - limit: int = 15, - fields: Optional[List[str]] = None, is_component: Optional[bool] = None, liked: bool = False, - ) -> Tuple[List[ListComponentResponse], List[Dict[str, Any]]]: - params = {"page": page, "limit": limit} - # ?aggregate[count]=likes - params["fields"] = ",".join(fields) if fields else ",".join(self.default_fields) - - if sort: - params["sort"] = ",".join(sort) - + api_key: Optional[str] = None, + ): filter_conditions = [] if search is not None: @@ -161,19 +149,18 @@ class StoreService(Service): filter_conditions.append({"status": {"_eq": status}}) if tags: - tags_filter = {"tags": {"_and": []}} - for tag in tags: - tags_filter["tags"]["_and"].append({"_some": {"tags_id": {"name": {"_eq": tag}}}}) + tags_filter = self.build_tags_filter(tags) filter_conditions.append(tags_filter) if is_component is not None: filter_conditions.append({"is_component": {"_eq": is_component}}) - if is_component is not None: - filter_conditions.append({"is_component": {"_eq": is_component}}) + liked_filter = self.build_liked_filter(liked, api_key) + filter_conditions.append(liked_filter) - # Only public components or the ones created by the user - # check for "public" or "Public" + return filter_conditions + + def build_liked_filter(self, liked: bool, api_key: Optional[str] = None): if liked and not api_key: raise ValueError("No API key provided") @@ -182,9 +169,32 @@ class StoreService(Service): # params["filter"] = json.dumps({"user_created": {"_eq": user_data["id"]}}) if not user_data: raise ValueError("No user data") - filter_conditions.append({"liked_by": {"_eq": user_data["id"]}}) + return {"liked_by": {"_eq": user_data["id"]}} else: - filter_conditions.append({"status": {"_in": ["public", "Public"]}}) + return {"status": {"_in": ["public", "Public"]}} + + def query_components( + self, + api_key: Optional[str] = None, + sort: Optional[List[str]] = None, + page: int = 1, + limit: int = 15, + fields: Optional[List[str]] = None, + is_component: Optional[bool] = None, + filter_conditions: Optional[List[Dict[str, Any]]] = None, + ) -> Tuple[List[ListComponentResponse], List[Dict[str, Any]]]: + params = {"page": page, "limit": limit} + # ?aggregate[count]=likes + params["fields"] = ",".join(fields) if fields else ",".join(self.default_fields) + + if sort: + params["sort"] = ",".join(sort) + + if is_component is not None: + filter_conditions.append({"is_component": {"_eq": is_component}}) + + # Only public components or the ones created by the user + # check for "public" or "Public" if filter_conditions: params["filter"] = json.dumps({"_and": filter_conditions}) @@ -195,7 +205,7 @@ class StoreService(Service): # for component in results_objects: # if component.tags: # component.tags = [tags_id.tags_id for tags_id in component.tags] - return results_objects, filter_conditions + return results_objects def get_liked_by_user_components(self, component_ids: List[UUID], api_key: str) -> List[UUID]: # Get fields id diff --git a/src/backend/langflow/services/utils.py b/src/backend/langflow/services/utils.py index f0fd91f1f..72807ee0c 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/langflow/services/utils.py @@ -2,24 +2,22 @@ from langflow.services.auth.utils import create_super_user, verify_password from langflow.services.database.utils import initialize_database from langflow.services.manager import service_manager from langflow.services.schema import ServiceType -from langflow.services.settings.constants import ( - DEFAULT_SUPERUSER, - DEFAULT_SUPERUSER_PASSWORD, -) -from sqlmodel import Session -from .deps import get_db_service, get_session, get_settings_service +from langflow.services.settings.constants import DEFAULT_SUPERUSER, DEFAULT_SUPERUSER_PASSWORD from loguru import logger +from sqlmodel import Session + +from .deps import get_db_service, get_session, get_settings_service def get_factories_and_deps(): - from langflow.services.database import factory as database_factory + from langflow.services.auth import factory as auth_factory from langflow.services.cache import factory as cache_factory from langflow.services.chat import factory as chat_factory - from langflow.services.settings import factory as settings_factory - from langflow.services.auth import factory as auth_factory - from langflow.services.task import factory as task_factory + from langflow.services.database import factory as database_factory from langflow.services.session import factory as session_service_factory # type: ignore + from langflow.services.settings import factory as settings_factory from langflow.services.store import factory as store_factory + from langflow.services.task import factory as task_factory return [ (settings_factory.SettingsServiceFactory(), []), @@ -170,8 +168,8 @@ def initialize_session_service(): """ Initialize the session manager. """ - from langflow.services.session import factory as session_service_factory # type: ignore from langflow.services.cache import factory as cache_factory + from langflow.services.session import factory as session_service_factory # type: ignore initialize_settings_service()