m_wikiconcept

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.wikiconceptResult
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_allConcepts ordered by local numeric ID, using request arguments page and pagelen (defaults 1 and 50).
totalNumber of imported concepts.

For example:

{% 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:

PathPayloadBehavior
insert/keywordwikidataReturn or create a keyword for the concept, returning {ok, ResourceId}.
connectwikidata, idConnect the concept to the keyword resource, replacing a previous connection.
disconnectwikidata, idDisconnect 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:

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

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.