# Learning opportunities index

Learning opportunities, services or courses are the basic entity for learning.

## Creating index

To create an index PUT to `https://search.eduplex.eu/example` being `example` the index name. You can add the mapping fields in the body.

See an example here: `https://gitlab.com/eduplex-api/opensearch/-/blob/main/files/index_mapping.json`

## Retrieving entries from index

To search on the index you can do a GET to `https://search.eduplex.eu/example/_search` being `example` the index name and with a body like this it will return all documents from the index.

```
{
  "query": {
    "match_all": {}
  }
}
```

We also have a proxy on our API to build more complex queries allowing to filter, return facets or rank results. Our endpoint allows the following parameters:

* **page**: pagination number.
* **limit**: number of documents per page.
* **text**: text to search.
* **semantic\_text**: same as previous parameter but using vector search with exact knn. You can not use both at the same time.
* **sort\_by**: it allows to sort by the following fields:
  * **title**
  * **total\_price**
  * **ratings**
  * **next\_course**
* **order**: it changes the sorting criteria (`asc` or `desc`)

and the following filters:

* **facets**: an object with different facets to filter. E.g.`{ type: 'online', city: 'Viena' }`.
* **tag**: returns only events associated to a specific tag.
* **category**: returns only events associated to a specific category.
* **seller\_id**: filters by the provider of the learning opportunities.
* **is\_internal**: returns only internal events.
* **has\_exclusive\_tag**: if `false` returns only events without exclusive tags.
* **exclusive\_tags**: if previous filter is set to `false`, also returns events with the specified tags.

## Examples

We use some special parameters to modify the results:

* **track\_scores**: it forces to calculate the score of the documents.
* **functions**: it allows to customize documents ranking scores.
* **score\_mode**: how to calculate the result from all the functions.
* **boost\_mode**: how to apply the `score_mode` to the document score.
* **aggs**: facets to be returned.

### Text search query

```
GET example_index/_search
{
  "from": 0,
  "size": 10,
  "track_scores": true,
  "query": {
    "function_score": {
      "score_mode": "sum",
      "boost_mode": "multiply", 
      "query": {
        "bool": {
          "must": [
            {
              "multi_match": {
                "query": "",
                "fields": [
                  "title^2",
                  "highlight",
                  "tags.display_name",
                  "categories.display_name",
                  "module_titles"
                ],
                "fuzziness": "AUTO",
                "zero_terms_query": "all"
              }
            }
          ]
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "provider_is_verified": true
            }
          },
          "weight": 1.2
        },
        {
          "filter": {
            "term": {
              "provider_is_topseller": true
            }
          },
          "weight": 1.2
        },
        {
          "filter": {
            "term": {
              "is_bookable": true
            }
          },
          "weight": 7
        },
        {
          "filter": {
            "term": {
              "has_boost": true
            }
          },
          "weight": 7
        },
        {
          "field_value_factor": {
            "field": "rating_rounded",
            "factor": 0.01,
            "missing": 250
          }
        }
      ]
    }
  },
  "aggs": {
    "tags.display_name": {
      "terms": {
        "field": "tags.display_name.keyword",
        "size": 100
      }
    },
    "language": {
      "terms": {
        "field": "language.keyword",
        "size": 10
      }
    },
    "categories.category": {
      "terms": {
        "field": "categories.category.keyword",
        "size": 100
      }
    },
    "provider.name": {
      "terms": {
        "field": "provider.name.keyword",
        "size": 100
      }
    }
  }
}
```

### Semantic search query

```
GET example_index/_search
{
  "from": 0,
  "size": 10,
  "track_scores": true,
  "query": {
    "function_score": {
      "score_mode": "sum",
      "boost_mode": "multiply", 
      "query": {
        "bool": {
          "must": [
            {
              "bool": {
                "should": [
                  {
                    "script_score": {
                      "query": {
                        "match_all": {}
                      },
                      "script": {
                        "source": "knn_score",
                        "lang": "knn",
                        "params": {
                          "field": "highlight_vector",
                          "query_value": [],
                          "space_type": "innerproduct"
                        }
                      }
                    }
                  }
                ]
              }
            }
          ]
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "provider_is_verified": true
            }
          },
          "weight": 1.2
        },
        {
          "filter": {
            "term": {
              "provider_is_topseller": true
            }
          },
          "weight": 1.2
        },
        {
          "filter": {
            "term": {
              "is_bookable": true
            }
          },
          "weight": 7
        },
        {
          "filter": {
            "term": {
              "has_boost": true
            }
          },
          "weight": 7
        },
        {
          "field_value_factor": {
            "field": "rating_rounded",
            "factor": 0.01,
            "missing": 250
          }
        }
      ]
    }
  },
  "aggs": {
    "tags.display_name": {
      "terms": {
        "field": "tags.display_name.keyword",
        "size": 100
      }
    },
    "language": {
      "terms": {
        "field": "language.keyword",
        "size": 10
      }
    },
    "categories.category": {
      "terms": {
        "field": "categories.category.keyword",
        "size": 100
      }
    },
    "provider.name": {
      "terms": {
        "field": "provider.name.keyword",
        "size": 100
      }
    }
  }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.eduplex.eu/opensearch/services-index.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
