# m\_wikiconcept

Source: https://zotonic.com/docs/3115/m_wikiconcept

URI: https://zotonic.com/id/3115

Language: en



Look up imported Wikidata/OpenAlex concepts, search their names and connect them to keyword resources. Concept rows are binary-keyed maps, with properties from `props_json` merged into the result. Imported text is not guaranteed to be safe HTML; escape it when displayed.

Read paths
----------

| Path under `m.wikiconcept` | Result                                                                           |
| -------------------------- | -------------------------------------------------------------------------------- |
| `id[identifier]`           | One concept by Wikidata Q-code, OpenAlex C-code or stored HTTPS URL.             |
| `find[identifier]`         | Alias for `id`; this is not a free-text search.                                  |
| `find_keyword[identifier]` | Best matching connected keyword resource ID.                                     |
| `connected[resource_id]`   | List of concepts connected to a resource.                                        |
| `list_all`                 | Concepts ordered by local numeric ID, using request arguments `page` and `pagelen` (defaults 1 and 50). |
| `total`                    | Number of imported concepts.                                                     |

For example:

```django
{% for concept in m.wikiconcept.connected[id] %}
    {{ concept.display_name|escape }}
{% endfor %}
```

Identifiers accept Q/C prefixes in either case, or an exact stored Wikidata, OpenAlex or Wikipedia HTTPS URL. A local numeric concept ID is not accepted by `get_concept/2`. Successful model reads return `{ok, {Value, Rest}}`; unknown identifiers return `{error, enoent}`. Unsupported model paths have no catch-all clause. Read paths do not check resource visibility or module permissions, including when returning connected keyword IDs.

`find_keyword/2` first uses the concept's own keyword, then the connected ancestor with the greatest level, then a connected descendant with the smallest level. It returns `{ok, ResourceId}` or `{error, enoent}`.

Write paths
-----------

POST to these model paths with a binary-keyed payload map:

| Path             | Payload          | Behavior                                                                      |
| ---------------- | ---------------- | ----------------------------------------------------------------------------- |
| `insert/keyword` | `wikidata`       | Return or create a keyword for the concept, returning `{ok, ResourceId}`.     |
| `connect`        | `wikidata`, `id` | Connect the concept to the keyword resource, replacing a previous connection. |
| `disconnect`     | `wikidata`, `id` | Disconnect the concept from the keyword resource.                             |

For example, the HTTP model endpoint for connecting is `/api/model/wikiconcept/post/connect`, with a JSON body such as `{"wikidata":"Q420","id":1234}`. The transport's authentication and topic ACLs apply independently of the model checks.

Connect/disconnect require `z_acl:rsc_editable/2` and a resource in the keyword category; failures return `eacces` or `enoent`. Their direct Erlang helpers do not repeat these ACL checks. Keyword insertion returns an existing connection or matching resource URI when available; otherwise it calls `m_rsc:insert/2`, trying the system content group and then the default group on `eacces`. Reusing a matching resource URI requires an editable keyword resource. `insert_keyword/3` accepts a category within the keyword subtree; `insert_keyword/2` defaults to `keyword`. Resource insertion checks the selected category and content group permissions. An already connected keyword is returned unchanged.

For direct Erlang calls with a selected keyword subcategory:

```erlang
m_wikiconcept:insert_keyword(<<"Q420">>, CategoryId, Context).
```

The model POST path uses the default `keyword` category; category selection is available through `insert_keyword/3` and the admin concept dialog.

New keywords are published and use the concept's translated `title` and `summary`. Each field retains nonempty translations matching the site's editable languages. If none match, a nonempty English translation is copied to `z_language:default_language/1`, independently of the current request language. For titles, missing English text falls back to `display_name`, then the supplied concept identifier. The resource's `language` property follows the resulting title translations. A summary without a matching or English translation is omitted.

Local search and remote import
------------------------------

```erlang
m_wikiconcept:find(<<"biology">>, 1, 20, Context).
m_wikiconcept:get_concept(<<"Q420">>, Context).
```

`find/2` defaults to offset 1 and limit 20. `find/4` uses a one-based offset, normalizes text and matches words against local names, using PostgreSQL trigram similarity for scoring. Empty search text lists concepts by display name. Results are `{ok, [ConceptMap]}` or an error. `count/2` returns the exact number of matching concepts using the same criteria, without pagination.

`find_descendant/2` defaults to offset 1 and limit 1000; `/4` accepts explicit pagination. It finds descendants one level below the first matching concept. `list_all_concepts/3` instead accepts a one-based page number and page size.

`fetch_all/1,2` fetch OpenAlex pages and return `{ok, {Concepts, done | {next, Cursor}}}` or an error. `load/1` downloads and stores the complete catalogue. Remote `fetch/2`, `openalex_search/3` and `openalex_autocomplete/3` return provider response data through `z_fetch`; they are separate from the local model lookup paths.

Installation and migration preserve existing rows and keyword links. `install_data/1` queues an import only for an empty catalogue; use the admin Reimport action to refresh populated tables. Imports update records by their Wikidata URL and reconcile search names while retaining keyword connections.

License: 

Attribution: 

Related resources: https://zotonic.com/api/agent/related/3115?language=en


## API access

- [API help](<https://zotonic.com/api-help>)
- [OpenAPI specification](<https://zotonic.com/openapi.json>)
- [This resource as JSON](<https://zotonic.com/api/agent/resource/3115?language=en>)
