1717from meilisearch import Client as MeilisearchClient
1818from meilisearch .errors import MeilisearchApiError , MeilisearchError
1919from meilisearch .models .task import TaskInfo
20- from opaque_keys .edx .keys import UsageKey , OpaqueKey
21- from opaque_keys .edx .locator import LibraryContainerLocator , LibraryLocatorV2 , LibraryCollectionLocator
20+ from opaque_keys import OpaqueKey
21+ from opaque_keys .edx .keys import UsageKey
22+ from opaque_keys .edx .locator import LibraryCollectionLocator , LibraryContainerLocator , LibraryLocatorV2
2223from openedx_learning .api import authoring as authoring_api
23- from common .djangoapps .student .roles import GlobalStaff
2424from rest_framework .request import Request
25+
2526from common .djangoapps .student .role_helpers import get_course_roles
27+ from common .djangoapps .student .roles import GlobalStaff
2628from openedx .core .djangoapps .content .course_overviews .models import CourseOverview
27- from openedx .core .djangoapps .content .search .models import get_access_ids_for_request , IncrementalIndexCompleted
2829from openedx .core .djangoapps .content .search .index_config import (
2930 INDEX_DISTINCT_ATTRIBUTE ,
3031 INDEX_FILTERABLE_ATTRIBUTES ,
31- INDEX_SEARCHABLE_ATTRIBUTES ,
32- INDEX_SORTABLE_ATTRIBUTES ,
3332 INDEX_RANKING_RULES ,
33+ INDEX_SEARCHABLE_ATTRIBUTES ,
34+ INDEX_SORTABLE_ATTRIBUTES
3435)
36+ from openedx .core .djangoapps .content .search .models import IncrementalIndexCompleted , get_access_ids_for_request
3537from openedx .core .djangoapps .content_libraries import api as lib_api
3638from xmodule .modulestore .django import modulestore
3739
3840from .documents import (
3941 Fields ,
4042 meili_id_from_opaque_key ,
41- searchable_doc_for_course_block ,
43+ searchable_doc_collections ,
4244 searchable_doc_for_collection ,
4345 searchable_doc_for_container ,
46+ searchable_doc_for_course_block ,
4447 searchable_doc_for_library_block ,
4548 searchable_doc_for_key ,
46- searchable_doc_collections ,
4749 searchable_doc_tags ,
48- searchable_doc_tags_for_collection ,
50+ searchable_doc_tags_for_collection
4951)
5052
5153log = logging .getLogger (__name__ )
@@ -487,6 +489,7 @@ def index_container_batch(batch, num_done, library_key) -> int:
487489 )
488490 doc = searchable_doc_for_container (container_key )
489491 doc .update (searchable_doc_tags (container_key ))
492+ doc .update (searchable_doc_collections (container_key ))
490493 docs .append (doc )
491494 except Exception as err : # pylint: disable=broad-except
492495 status_cb (f"Error indexing container { container .key } : { err } " )
@@ -709,15 +712,15 @@ def upsert_library_collection_index_doc(library_key: LibraryLocatorV2, collectio
709712 If the Collection is not found or disabled (i.e. soft-deleted), then delete it from the search index.
710713 """
711714 doc = searchable_doc_for_collection (library_key , collection_key )
712- update_components = False
715+ update_items = False
713716
714717 # Soft-deleted/disabled collections are removed from the index
715718 # and their components updated.
716719 if doc .get ('_disabled' ):
717720
718721 _delete_index_doc (doc [Fields .id ])
719722
720- update_components = True
723+ update_items = True
721724
722725 # Hard-deleted collections are also deleted from the index,
723726 # but their components are automatically updated as part of the deletion process, so we don't have to.
@@ -735,10 +738,12 @@ def upsert_library_collection_index_doc(library_key: LibraryLocatorV2, collectio
735738 _update_index_docs ([doc ])
736739
737740 # Asynchronously update the collection's components "collections" field
738- if update_components :
739- from .tasks import update_library_components_collections as update_task
741+ if update_items :
742+ from .tasks import update_library_components_collections as update_components_task
743+ from .tasks import update_library_containers_collections as update_containers_task
740744
741- update_task .delay (str (library_key ), collection_key )
745+ update_components_task .delay (str (library_key ), collection_key )
746+ update_containers_task .delay (str (library_key ), collection_key )
742747
743748
744749def update_library_components_collections (
@@ -773,6 +778,38 @@ def update_library_components_collections(
773778 _update_index_docs (docs )
774779
775780
781+ def update_library_containers_collections (
782+ library_key : LibraryLocatorV2 ,
783+ collection_key : str ,
784+ batch_size : int = 1000 ,
785+ ) -> None :
786+ """
787+ Updates the "collections" field for all containers associated with a given Library Collection.
788+
789+ Because there may be a lot of containers, we send these updates to Meilisearch in batches.
790+ """
791+ library = lib_api .get_library (library_key )
792+ containers = authoring_api .get_collection_containers (library .learning_package_id , collection_key )
793+
794+ paginator = Paginator (containers , batch_size )
795+ for page in paginator .page_range :
796+ docs = []
797+
798+ for container in paginator .page (page ).object_list :
799+ container_key = lib_api .library_container_locator (
800+ library_key ,
801+ container ,
802+ )
803+ doc = searchable_doc_collections (container_key )
804+ docs .append (doc )
805+
806+ log .info (
807+ f"Updating document.collections for library { library_key } containers"
808+ f" page { page } / { paginator .num_pages } "
809+ )
810+ _update_index_docs (docs )
811+
812+
776813def upsert_library_container_index_doc (container_key : LibraryContainerLocator ) -> None :
777814 """
778815 Creates, updates, or deletes the document for the given Library Container in the search index.
@@ -819,12 +856,12 @@ def upsert_content_object_tags_index_doc(key: OpaqueKey):
819856 _update_index_docs ([doc ])
820857
821858
822- def upsert_block_collections_index_docs ( usage_key : UsageKey ):
859+ def upsert_item_collections_index_docs ( opaque_key : OpaqueKey ):
823860 """
824- Updates the collections data in documents for the given Course/Library block
861+ Updates the collections data in documents for the given Course/Library block, or Container
825862 """
826- doc = {Fields .id : meili_id_from_opaque_key (usage_key )}
827- doc .update (searchable_doc_collections (usage_key ))
863+ doc = {Fields .id : meili_id_from_opaque_key (opaque_key )}
864+ doc .update (searchable_doc_collections (opaque_key ))
828865 _update_index_docs ([doc ])
829866
830867
0 commit comments