from django.conf import settings import certifi from pymongo import MongoClient from django.db.models import Case, When, IntegerField from projects.models import Project from portfolios.models import Portfolio NOCODETOOL_MODEL_MAP = { 'project': Project, 'portfolio': Portfolio, } class NocodetoolSearchService: @staticmethod def search(search_term, object_type, page, page_size): client = MongoClient(settings.MONGODB_URI, tlsCAFile=certifi.where()) db = client[settings.MONGODB_NAME] coll = db["code"] filters = [] if object_type in ("project", "portfolio"): filters.append({"term": {"path": "object_type", "query": object_type}}) pipeline = [ { "$search": { "index": "nocodetool_content_keyword_search_index", "compound": { "filter": filters, "should": [ { "text": { "query": search_term, "path": "keyword", "score": {"boost": {"value": 5}} } }, { "text": { "query": search_term, "path": "pages.elements.content", "score": {"boost": {"value": 10}} } }, { "text": { "query": search_term, "path": "description", "score": {"boost": {"value": 7}} } } ], "minimumShouldMatch": 1 } } }, { "$project": { "keyword": 1, "description": 1, "pages.elements.content": 1, "object_type": 1, "object_id": 1, "score": {"$meta": "searchScore"} } }, { "$facet": { "projects": [ {"$match": {"object_type": "project"}}, {"$sort": {"score": -1}}, {"$skip": (page - 1) * page_size}, {"$limit": page_size} ], "portfolios": [ {"$match": {"object_type": "portfolio"}}, {"$sort": {"score": -1}}, {"$skip": (page - 1) * page_size}, {"$limit": page_size} ] } } ] agg_result = list(coll.aggregate(pipeline)) print(agg_result) buckets = agg_result[0] if agg_result else {"projects": [], "portfolios": []} return buckets def get_ids_from_buckets(buckets: list) -> list: return [object["object_id"] for object in buckets] class NocodetoolToObjectService: def get_objects_by_ids(object_type, objects_ids: list) -> list: if not objects_ids: return [] order = Case( *[When(id=pk, then=pos) for pos, pk in enumerate(objects_ids)], output_field=IntegerField() ) object_model = NOCODETOOL_MODEL_MAP.get(object_type) if not object_model: return [] return list(object_model.objects.filter(id__in=objects_ids).order_by(order))