mitodl / mitodl/mit-learn

Use Opensearch for learning resource API results whenever feasible

Open
#189 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
3
Forks
4
Avg merge
2d 3h
Merged PRs (30d)
114

Description

Description/Context

Use opensearch for API results for lists when feasible (ie not for lists of learning paths requested by editors, perhaps other exceptions) and perhaps single object results as well.

Plan/Design

Option 1: OpenSearch endpoint for lists, database endpoints for individual objects and learning path CRUD

Continue using the database to return:

  • Published individual learning resource details (url: /api/v1/learning_resources/<pk>/, /api/v1/courses/<pk>/, etc)
  • Published child resources of a resource (url: /api/v1/learning_resources/<pk>/children/). Example: episodes in a podcast, resources in a learning path

Provide a new database-backed API endpoint - /api/v1/learning_path_admin/ - specifically for learning paths CRUD. This will return specific path details as well as lists of learning paths, both published and unpublished. Only users with editing permission will be allowed to access it.

Use opensearch for all read-only learning resource list endpoints (published only):

  • /api/v1/learning_resources/, /api/v1/courses/, /api/v1/programs/, etc
  • /api/v1/learning_resources/new/ (need to add created_on values to the index and sort by that)
  • api/v1/learning_resources/upcoming/ (need to build an opensearch query filtering by runs.published and (runs.start_date or runs.enrollment_start) then ordering by runs.start_date)

Separate views will be used for each:

  • learning_resources.views.LearningResourceViewSet(RetrieveModelMixin, viewsets.GenericViewSet) for individual objects and their children
  • learning_resources.views.LearningPathAdminViewSet(viewsets.ModelViewSet) for learning path CRUD
  • learning_resources_search.views.LearningResourcesSearchView(ESView) for lists of learning resources.

URL's would have to be loaded in the following order in open_discussions/urls.py:

    re_path(r"", include("learning_resources.urls")),
    re_path(r"", include("learning_resources_search.urls")),
Option 2: OpenSearch endpoint for lists and individual results, database for learning path editing only.

Similar to above, but use opensearch for individual object results and child resources of individual results

  • Would need to adjust serializers so that each child resource document in opensearch includes a parents field indicating the relation (and type of relation) to other resources. For example, /api/v1/podcasts/<id>/episodes could not rely on database relationships to get correct results, would need to query opensearch where parent_id=<id> and relation_type=podcast,

Separate views will be used for each:

  • learning_resources.views.LearningPathViewSet(viewsets.ModelViewSet) for learning path CRUD
  • learning_resources_search.views.LearningResourcesSearchView(ESView) for learning resources lists and individual objects
Option 3: Conditionally switch to an opensearch API view from a database API view, depending on parameters.
  @extend_schema(responses=LearningResourceSerializer(many=True))
  @action(methods=["GET"], detail=False, name="New Resources")
  def new(self, request: Request) -> QuerySet:  # noqa: ARG002
      if self.use_database():  # query param of db=True, or path editor requesting list of all paths
     
          page = self.paginate_queryset(self.get_queryset().order_by("-created_on"))
          serializer = self.get_serializer(page, many=True)
          return self.get_paginated_response(serializer.data)

      return LearningResourcesSearchView().get(request, sortby="-created_on")   
      # or insert the code from the view above here directly.

This does not seem like the best approach, for several reasons:

  • It mixes views from two different apps, which does not seem like good practice

  • Need to ensure that the different views always accept the same query parameters and apply filters consistently.

  • The views may have slightly different outputs. For example, the current search endpoint does not include next and previous page attributes, though maybe it should. And the current database-backed endpoint never includes this data structure:

    "metadata": {
        "aggregations": {},
        "suggest": []
    }
    

    Though again, the outputs could probably be made consistent, up to a point (if using database, can't get actual values for those metadata fields, other than empty ones like above).

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by comparing the existing endpoints in learning_resources.views, learning_resources_search.views, their URLs, and open_discussions/urls.py. Review the three proposed options and the current search response and filters before choosing an approach. Done means the selected published list endpoints use OpenSearch while learning path editing and any documented database-backed exceptions continue to work consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend, search
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.