{"result":{"depiction_url":null,"edges":{"in_module":{"objects":[{"created":"2026-09-09T13:48:13Z","object_id":{"id":335,"is_a":["text","documentation","reference","module"],"name":"doc_core","title":"Zotonic Core","uri":"https:\/\/zotonic.com\/id\/335"},"seq":1}],"predicate":{"id":333,"is_a":["meta","predicate"],"name":"in_module","title":{"_type":"trans","tr":{"en":"In module"}},"uri":"https:\/\/zotonic.com\/id\/in_module"}},"references":{"objects":[{"created":"2020-05-30T05:47:55Z","object_id":{"id":1278,"is_a":["text","documentation","reference","model"],"name":"doc_model_model_rsc","title":"rsc","uri":"https:\/\/zotonic.com\/id\/1278"},"seq":1000000}],"predicate":{"id":332,"is_a":["meta","predicate"],"name":"references","title":{"_type":"trans","tr":{"en":"References"}},"uri":"https:\/\/zotonic.com\/id\/references"}},"refers":{"objects":[{"created":"2026-09-09T13:48:13Z","object_id":{"id":1278,"is_a":["text","documentation","reference","model"],"name":"doc_model_model_rsc","title":"rsc","uri":"https:\/\/zotonic.com\/id\/1278"},"seq":1000000}],"predicate":{"id":2409,"is_a":["meta","predicate"],"name":"refers","title":{"_type":"trans","tr":{"en":"Refers"}},"uri":"https:\/\/zotonic.com\/id\/refers"}},"relation":{"objects":[{"created":"2020-05-30T05:47:55Z","object_id":{"id":1278,"is_a":["text","documentation","reference","model"],"name":"doc_model_model_rsc","title":"rsc","uri":"https:\/\/zotonic.com\/id\/1278"},"seq":1000000},{"created":"2020-05-30T05:47:55Z","object_id":{"id":1284,"is_a":["text","documentation","reference","model"],"name":"doc_model_model_media","title":"media","uri":"https:\/\/zotonic.com\/id\/1284"},"seq":1000000}],"predicate":{"id":303,"is_a":["meta","predicate"],"name":"relation","title":{"_type":"trans","tr":{"nl":"Relatie","en":"Relation"}},"uri":"http:\/\/purl.org\/dc\/terms\/relation"}},"subject":{"objects":[{"created":"2026-09-09T13:48:13Z","object_id":{"id":2555,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_reference","title":"Reference","uri":"https:\/\/zotonic.com\/id\/2555"},"seq":1},{"created":"2026-09-09T13:48:13Z","object_id":{"id":2564,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_backend_developer","title":"Backend developer","uri":"https:\/\/zotonic.com\/id\/2564"},"seq":2},{"created":"2026-09-09T13:48:13Z","object_id":{"id":2574,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_content_relationships","title":"Content relationships","uri":"https:\/\/zotonic.com\/id\/2574"},"seq":3},{"created":"2026-09-09T13:48:13Z","object_id":{"id":2617,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_edge","title":"Edge","uri":"https:\/\/zotonic.com\/id\/2617"},"seq":4},{"created":"2026-09-09T13:48:13Z","object_id":{"id":2625,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_model","title":"Model","uri":"https:\/\/zotonic.com\/id\/2625"},"seq":5},{"created":"2026-09-09T13:48:13Z","object_id":{"id":2643,"is_a":["categorization","keyword","keyword_task"],"name":"zotonic_topic_query","title":"Query","uri":"https:\/\/zotonic.com\/id\/2643"},"seq":6}],"predicate":{"id":308,"is_a":["meta","predicate"],"name":"subject","title":{"_type":"trans","tr":{"en":"Keyword"}},"uri":"http:\/\/purl.org\/dc\/elements\/1.1\/subject"}}},"id":1297,"is_a":["text","documentation","reference","model"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1297"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_model_model_edge","page_url":{"en":"https:\/\/zotonic.com\/docs\/1297\/edge","x-default":"https:\/\/zotonic.com\/docs\/1297\/edge"},"preview_url":null,"resource":{"version":3326,"pivot_location_lat":null,"title":"edge","is_authoritative":true,"body":"<p>Access information about page connections.<\/p>\n<p>Edges represent the connections between resources. They are implemented as tuples <code>{EdgeId, SubjectId, PredicateId, ObjectId, OrderNr}<\/code>. The edge id is a unique id representing the edge, it can be used with edit actions. The OrderNr defines the\norder of the edges with respect to the subject.<\/p>\n<p>Most edge information is accessed using the <a href=\"\/id\/doc_model_model_rsc\" class=\"doc-reference doc-reference-model\"><code>model#rsc<\/code><\/a> model, but some information can only\naccessed with the m_edge model.<\/p>\n<p>This model implements two template accessible options. They are mainly used to obtain the edge&#39;s id for edit pages.<\/p>\n<p>The following m_edge model properties are available in templates:<\/p>\n<table class=\"table\"><thead><tr><th>Property<\/th><th>Description<\/th><th>Example value<\/th><\/tr><\/thead><tbody><tr><td>o<\/td><td>Returns a function that accepts a page  id and a predicate. The end result is a list of tuples {PageId, EdgeId} which are objects of the page. Example usage: <code>m.edge.o[id].author<\/code><\/td><td><code>[{204,13},{510,14}, {508,15}]<\/code><\/td><\/tr><tr><td>s<\/td><td>Identical to the &quot;o&quot; property, except that this function returns the subject edges.<\/td><td><\/td><\/tr><tr><td>o_props<\/td><td>Similar to <code>m.edge.o[id].author<\/code> above, but returns a property list for the edges instead of the 2-tuple.<\/td><td><code>&gt; [ &gt; {id, 86062}, &gt; {subject_id, 10635}, &gt; {predicate_id, 304}, &gt; {object_id, 57577}, &gt; {seq, 1}, &gt; {creator_id, 1}, &gt; {created, { &gt; {2015,11,17}, &gt; {11,23,32} &gt; }} &gt; ] &gt; ]<\/code><\/td><\/tr><tr><td>s_props<\/td><td>Similar to <code>m.edge.s[id].author<\/code> above, but returns a property list for the edges instead of the 2-tuple.<\/td><td><\/td><\/tr><tr><td>edges<\/td><td>Returns a function that accepts a page id. The end result is a list of edges per predicate where the predicate is an atom and the edges are property lists. Example usage: <code>m.edge[10635]<\/code><\/td><td><code>See example below.<\/code><\/td><\/tr><tr><td>id<\/td><td>Look up an edge id by a subject\/predicate\/object triple. Example usage:   <code>erlang m.edge.id[subject_id].relation[object_id] <\/code>  or:   <code>erlang m.edge.id[subject_id][predicate_name][object_id] <\/code>  Returns <code>undefined<\/code> if the edge does not exist; otherwise returns an integer.<\/td><td><code>213<\/code><\/td><\/tr><\/tbody><\/table>\n<p>Example return value for <code>{% print m.edge[10635] %}<\/code>:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-erlang\">[{about,[[{id,86060},\n          {subject_id,10635},\n          {predicate_id,300},\n          {name,&lt;&lt;&quot;about&quot;&gt;&gt;},\n          {object_id,17433},\n          {seq,1},\n          {created,{{2015,11,17},{11,22,11}}},\n          {creator_id,1}]]},\n {author,[[{id,6},\n           {subject_id,10635},\n           {predicate_id,301},\n           {name,&lt;&lt;&quot;author&quot;&gt;&gt;},\n           {object_id,10634},\n           {seq,1000000},\n           {created,{{2015,2,3},{16,23,20}}},\n           {creator_id,1}]]}]\n<\/code><\/pre>\n<h2>Other Topics<\/h2>\n<p><code>model\/edge\/post\/o\/+subject\/+predicate\/+object<\/code> or <code>model\/edge\/post\/s\/+object\/+predicate\/+subject<\/code> inserts a new edge between resources.<\/p>\n<p>The posted message can optionally include the name or id of the object, predicate and subject.<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.publish(&quot;bridge\/origin\/edge\/post\/o\/4312&quot;,\n                       {\n                         predicate: &quot;author&quot;,\n                         subject: 7575\n                       });\n<\/code><\/pre>\n<p>It is also possible to insert edges via cotonics onclick topics.<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-django\">&lt;div data-onclick-topic=&quot;bridge\/origin\/model\/edge\/post\/o\/{{ id }}\/?\/{{ m.acl.user }}&quot;&gt;\n   &lt;button data-edge-predicate=&quot;is_going&quot;&gt;Is Going&lt;\/button&gt;\n   &lt;button data-edge-predicate=&quot;is_interested&quot;&gt;Might Go&lt;\/button&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n<p>When a user clicks on a button, the model retrieves the predicate name (or id) from the <code>data-edge-predicate<\/code> attribute.\nThis is also possible by for the object and subject attributes of the edge. When there is a <code>?<\/code> in the topic path, the\nvalue can be retrieved from a data attribute. The attribute value for object is: <code>data-edge-object<\/code>. For subject it is: <code>data-edge-subject<\/code>.\nIf all path parts from the first <code>?<\/code> to the end are <code>?<\/code>, then those trailing <code>?<\/code> parts may be omitted from the topic path.<\/p>\n<p><code>model\/edge\/delete\/o\/+subject\/+predicate\/+object<\/code>, <code>model\/edge\/delete\/s\/+object\/+predicate\/+subject<\/code> or <code>model\/edge\/delete\/edge\/+edge_id<\/code> deletes the specified edge.<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.publish(&quot;bridge\/origin\/edge\/delete\/edge\/6776&quot;);\n<\/code><\/pre>\n<p>Or via a onclick topic.<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-django\">&lt;button data-onclick-topic=&quot;bridge\/origin\/edge\/delete\/{{ edge_id }}&quot;&gt;Delete&lt;\/button\n<\/code><\/pre>\n<h2>Available Model API Paths<\/h2>\n<table class=\"table\"><thead><tr><th>Method<\/th><th>Path pattern<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td><code>get<\/code><\/td><td><code>\/o\/+id\/+pred\/...<\/code><\/td><td>Return outgoing edge tuples <code>{ObjectId, EdgeId}<\/code> from subject <code>+id<\/code> for predicate <code>+pred<\/code> (subject must be visible).<\/td><\/tr><tr><td><code>get<\/code><\/td><td><code>\/o_props\/+id\/+pred\/...<\/code><\/td><td>Return outgoing edge rows (id\/subject\/predicate\/object\/seq\/created\/creator) from subject <code>+id<\/code> for predicate <code>+pred<\/code>.<\/td><\/tr><tr><td><code>get<\/code><\/td><td><code>\/s\/+id\/+pred\/...<\/code><\/td><td>Return incoming edge tuples <code>{SubjectId, EdgeId}<\/code> pointing to object <code>+id<\/code> for predicate <code>+pred<\/code> (object must be visible).<\/td><\/tr><tr><td><code>get<\/code><\/td><td><code>\/s_props\/+id\/+pred\/...<\/code><\/td><td>Return incoming edge rows (id\/subject\/predicate\/object\/seq\/created\/creator) for object <code>+id<\/code> and predicate <code>+pred<\/code>.<\/td><\/tr><tr><td><code>get<\/code><\/td><td><code>\/edges\/+id\/...<\/code><\/td><td>Return all outgoing edges of resource <code>+id<\/code> grouped by predicate name.<\/td><\/tr><tr><td><code>get<\/code><\/td><td><code>\/id\/+subjectid\/+pred\/+objectid\/...<\/code><\/td><td>Return edge id for (<code>+subjectid<\/code>, <code>+pred<\/code>, <code>+objectid<\/code>) or <code>undefined<\/code> if absent (subject must be visible).<\/td><\/tr><tr><td><code>get<\/code><\/td><td><code>\/graph\/...<\/code><\/td><td>Return graph map (<code>nodes<\/code>, <code>edges<\/code>, <code>is_truncated<\/code>) for payload <code>ids<\/code>, with optional payload options <code>limit<\/code> and <code>unescape<\/code>.<\/td><\/tr><tr><td><code>get<\/code><\/td><td><code>\/+id<\/code><\/td><td>Return same grouped outgoing-edge data as <code>\/edges\/+id<\/code> for resource <code>+id<\/code>. No further lookups.<\/td><\/tr><tr><td><code>post<\/code><\/td><td><code>\/o\/...<\/code><\/td><td>Insert one edge using object-oriented argument order <code>(subject, predicate, object)<\/code>; values come from path segments, payload keys, <code>message.data-edge-*<\/code>, or query args.<\/td><\/tr><tr><td><code>post<\/code><\/td><td><code>\/s\/...<\/code><\/td><td>Insert one edge using subject-oriented path order <code>(object, predicate, subject)<\/code>; stored edge is still <code>(subject, predicate, object)<\/code>.<\/td><\/tr><tr><td><code>delete<\/code><\/td><td><code>\/o\/...<\/code><\/td><td>Delete edge(s) using object-oriented order <code>(subject, predicate, object)<\/code>.<\/td><\/tr><tr><td><code>delete<\/code><\/td><td><code>\/s\/...<\/code><\/td><td>Delete edge(s) using subject-oriented path order <code>(object, predicate, subject)<\/code>; this maps to stored triple <code>(subject, predicate, object)<\/code>.<\/td><\/tr><tr><td><code>delete<\/code><\/td><td><code>\/edge\/+edge<\/code><\/td><td>Delete a single edge by edge id <code>+edge<\/code> (invalid id returns <code>enoent<\/code>). No further lookups.<\/td><\/tr><\/tbody><\/table>\n<p><code>\/+name<\/code> marks a variable path segment. A trailing <code>\/...<\/code> means extra path segments are accepted for further lookups.<\/p>\n<h2>Post Method Examples<\/h2>\n<p>Path orientation notes:<\/p>\n<ul><li>Object-oriented path (<code>\/o\/...<\/code>) uses order: <code>subject \/ predicate \/ object<\/code>.<\/li><li>Subject-oriented path (<code>\/s\/...<\/code>) uses order: <code>object \/ predicate \/ subject<\/code>.<\/li><li>Both forms create or delete the same edge triple in storage: <code>(subject, predicate, object)<\/code>.<\/li><li>Trailing wildcard parts can be omitted: if all path parts from the first <code>?<\/code> to the end are <code>?<\/code>, you may stop the path at that first <code>?<\/code>.<\/li><\/ul>\n<p>Insert via object-oriented path:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.call(\n    &quot;bridge\/origin\/model\/edge\/post\/o\/7575\/author\/4312&quot;,\n    {}\n);\n<\/code><\/pre>\n<p>Insert via wildcard path values (<code>?<\/code>) resolved from payload:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.call(\n    &quot;bridge\/origin\/model\/edge\/post\/o\/?\/?\/?&quot;,\n    {\n        subject: 7575,\n        predicate: &quot;author&quot;,\n        object: 4312\n    }\n);\n<\/code><\/pre>\n<p>Insert with trailing wildcards omitted (only subject in path, predicate\/object from payload):<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.call(\n    &quot;bridge\/origin\/model\/edge\/post\/o\/7575&quot;,\n    {\n        predicate: &quot;author&quot;,\n        object: 4312\n    }\n);\n<\/code><\/pre>\n<p>Insert with all values from payload (shortest path):<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.call(\n    &quot;bridge\/origin\/model\/edge\/post\/o&quot;,\n    {\n        subject: 7575,\n        predicate: &quot;author&quot;,\n        object: 4312\n    }\n);\n<\/code><\/pre>\n<p>Insert via subject-oriented path:<\/p>\n<pre class=\"notranslate\"><code class=\"notranslate language-javascript\">cotonic.broker.call(\n    &quot;bridge\/origin\/model\/edge\/post\/s\/4312\/author\/7575&quot;,\n    {}\n);\n<\/code><\/pre>","slug":"edge","is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"doc_source_hash":"82d0de5d028569e72187cbdcc1c4cc08b00ea190557e0296301560682f96a703","is_featured":false,"content_group_id":{"id":2551,"is_a":["meta","content_group"],"name":"content_group_imported_docs","title":"Imported documentation","uri":"https:\/\/zotonic.com\/id\/content_group_imported_docs"},"category_id":{"id":322,"is_a":["meta","category"],"name":"model","title":"Models","uri":"https:\/\/test.zotonic.com\/id\/322"},"doc_source_path":"apps\/zotonic_core\/src\/models\/m_edge.erl","publication_start":"2023-01-30T19:23:55Z","github_url":"https:\/\/github.com\/zotonic\/zotonic\/blob\/master\/apps\/zotonic_core\/src\/models\/m_edge.erl","pivot_location_lng":null,"doc_source_kind":"model","name":"doc_model_model_edge","is_unfindable":false,"is_published":true,"pivot_geocode":null,"created":"2020-05-30T05:47:17Z","uri":null,"doc_status":"current","is_dependent":false,"erlang_app":"zotonic_core","publication_end":"9999-06-01T00:00:00Z","modifier_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"privacy":0,"doc_source_commit":"b8c4b2ccdc223257f311968fbd17b2d66f0c4156\n","erlang_module":"m_edge","creator_id":{"id":336,"is_a":["person","robot"],"name":"gitbot","title":"Git","uri":"https:\/\/zotonic.com\/id\/336"},"modified":"2026-09-30T09:39:54Z","title_slug":"edge"},"uri":"https:\/\/zotonic.com\/id\/1297","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1297"}},"status":"ok"}