diff --git a/annif/openapi/annif.yaml b/annif/openapi/annif.yaml index 317922298..531b0657d 100644 --- a/annif/openapi/annif.yaml +++ b/annif/openapi/annif.yaml @@ -242,6 +242,12 @@ paths: "versions": [ "0.2" ], + "suggest": { + "entity": { + "service_path": "/suggest/entity", + "service_url": "/v1/projects/dummy-fi/reconcile" + } + }, "view": { "url": "{{id}}" } @@ -276,7 +282,7 @@ paths: post: tags: - Reconciliation - summary: reconcole against a project + summary: reconcile against a project operationId: annif.rest.reconcile parameters: - $ref: '#components/parameters/project_id' @@ -326,6 +332,36 @@ paths: $ref: '#/components/schemas/ReconciliationResult' "404": $ref: '#/components/responses/NotFound' + /projects/{project_id}/reconcile/suggest/entity: + get: + tags: + - Reconciliation + summary: Entity auto-complete endpoint for the reconciliation service + operationId: annif.rest.reconcile_suggest + parameters: + - $ref: '#components/parameters/project_id' + - in: query + description: string to get suggestions for + name: prefix + required: true + schema: + type: string + example: example query + - in: query + description: number of suggestions to skip + name: cursor + required: false + schema: + type: integer + responses: + "200": + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ReconcileSuggestResult' + "404": + $ref: '#/components/responses/NotFound' components: schemas: ApiInfo: @@ -559,6 +595,25 @@ components: ] } } + ReconcileSuggestResult: + type: object + required: + - result + properties: + result: + type: array + items: + type: object + required: + - name + - id + properties: + name: + type: string + example: example name + id: + type: string + example: example-id Problem: type: object properties: diff --git a/annif/rest.py b/annif/rest.py index cfb3d8545..bc57689ee 100644 --- a/annif/rest.py +++ b/annif/rest.py @@ -256,6 +256,14 @@ def reconcile_metadata( "schemaSpace": "http://www.w3.org/2004/02/skos/core#Concept", "view": {"url": "{{id}}"}, "defaultTypes": [{"id": "default-type", "name": "Default type"}], + "suggest": { + "entity": { + "service_path": "/suggest/entity", + "service_url": "http://localhost:5000/v1/projects/" + + project_id + + "/reconcile", # change to actual host url (how?) + } + }, } else: queries = json.loads(query_parameters["queries"]) @@ -284,3 +292,21 @@ def reconcile( results[key] = {"result": data} return results + + +def reconcile_suggest( + project_id: str, **query_parameters +) -> ConnexionResponse | dict[str, Any]: + """suggest results for the given search term and return a dict with results + formatted according to OpenAPI spec""" + + prefix = query_parameters.get("prefix") + cursor = query_parameters.get("cursor") if query_parameters.get("cursor") else 0 + limit = cursor + 10 + + result = _suggest(project_id, [{"text": prefix}], {"limit": limit}) + if _is_error(result): + return result + + results = [{"id": res["uri"], "name": res["label"]} for res in result[0]["results"]] + return {"result": results[cursor:]} diff --git a/tests/test_openapi.py b/tests/test_openapi.py index de1189515..b1dfa5399 100644 --- a/tests/test_openapi.py +++ b/tests/test_openapi.py @@ -160,3 +160,18 @@ def test_openapi_reconcile_nonexistent(app_client): "http://localhost:8000/v1/projects/nonexistent/reconcile", data=data ) assert req.status_code == 404 + + +def test_openapi_reconcile_suggest(app_client): + req = app_client.get( + "http://localhost:8000/v1/projects/dummy-fi/reconcile/suggest/entity?prefix=example" + ) + assert req.status_code == 200 + assert "result" in req.get_json() + + +def test_openapi_reconcile_suggest_nonexistent(app_client): + req = app_client.get( + "http://localhost:8000/v1/projects/nonexistent/reconcile/suggest/entity?prefix=example" + ) + assert req.status_code == 404 diff --git a/tests/test_rest.py b/tests/test_rest.py index 104999cc6..51c698137 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -277,3 +277,15 @@ def test_rest_reconcile_nonexistent(app): "nonexistent", {"queries": {"q0": {"query": "example text"}}} ) assert result.status_code == 404 + + +def test_rest_reconcile_suggest(app): + with app.app_context(): + results = annif.rest.reconcile_suggest("dummy-fi", prefix="example text") + assert "result" in results + + +def test_rest_reconcile_nonexistent(app): + with app.app_context(): + result = annif.rest.reconcile_suggest("nonexistent", prefix="example text") + assert result.status_code == 404