/model/relations
endpoint manages relations between object types.
This is one of the most important features in BEdita: you can create dynamic semantic relations between object types, adding constraint rules and parameters without any data model or database modification.
Relations in BEdita have been heavily inspired by semantic web RDF triples.
Every relation should be expressed in a form {subject} {predicate} {object}
where both {subject}
and {object}
are BEdita objects and {predicate}
is the relation name.
In BEdita for every relation an inverse one is also created, this will be more clear in the example below.
With this endpoint you can:
- create, update/remove an object relation
- list available relations
- handle which object types are involved in a relation
Creation of a new relation happens through POST /model/relations
endpoint.
.. http:post:: /model/relations
Example request - create relation:
POST /model/relations HTTP/1.1
Host: api.example.com
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
{
"data": {
"type": "relations",
"attributes": {
"name": "owner_of",
"label": "Owner of",
"inverse_name": "belong_to",
"inverse_label": "Belong to",
"description": "Cat owner relation"
}
}
}
Required attributes creating a new relation are:
name
principal relation nameinverse_name
inverse relation name
Both attributes must be different and unique inside the project, should differ from property names of object types involved in this relation and as naming convention should also be expressed as a _predicate_ linking object types together.
They also must be in lowered snake_case format as internal naming convention.
Our goal in this example, although not yet complete, is to create the relation [users] [owner_of] [cats]
and its inverse [cats] [belong_to] [users]
.
Other optional attributes are
label
alternative text to show instead ofname
inverse_label
alternative text to show instead ofinverse_name
description
optional description of the relation
Expected response is HTTP/1.1 201 OK
, with application/vnd.api+json
body data representing relation just created.
If the relation already exists or data is not valid (i.e. lacks of required fields or inconsistent input), POST fails and response will be 400 Bad Request - Invalid data
.
You can obtain a single relation by invoking GET /model/relations/{relation}
.
.. http:get:: /model/relations/{relation}
{relation}
can be a numeric id of the relation, itsname
orinverse_name
Example request (get a relation):
GET /model/relations/owner_of HTTP/1.1
Host: api.example.com
Accept: application/vnd.api+json
Example response:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": {
"id": "1",
"type": "relations",
"attributes": {
"name": "owner_of",
"label": "Owner of",
"inverse_name": "belong_to",
"inverse_label": "Belong to",
"description": "Cat owner relation",
"params": {}
},
"relationships": {
"left_object_types": {
"links": {
"related": "http://api.example.com/model/relations/1/left_object_types",
"self": "http://api.example.com/model/relations/1/relationships/left_object_types"
}
},
"right_object_types": {
"links": {
"related": "http://api.example.com/model/relations/1/right_object_types",
"self": "http://api.example.com/model/relations/1/relationships/right_object_types"
}
}
}
},
"links": {
"self": "http://api.example.com/model/relations/owner_of",
"home": "http://api.example.com/home"
}
}
Example response shows us something interesting in "relationships"
section:
"left_object_types"
links object types to use on _the_ left side of the relation, think of thesubject
in thesubject predicate object
expression, i.e. object types that areowner_of
other object types (on the _right_ side)"right_object_types"
links object types to use on the _right_ side of the relation, think of theobject
in thesubject predicate object
expression, i.e. object types thatbelong_to
object types on the _left_ side
To retrieve a list of relations you can simply invoke GET /model/relations
and use common filters like :ref:`filter-field` or :ref:`filter-search`
.. http:get:: /model/relations
Example request: get relations:
GET /model/relations?filter[name]=owner_of HTTP/1.1
Accept: application/vnd.api+json
Response will contain an array of relations
in typical list format as shown in :ref:`api-responses`.
In this particular case response content in "data"
section will be the same as in the previous example, here below a reduced version of it for brevity.
Example response: get relations:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": [{
"id": "1",
"type": "relations",
"attributes": {
"name": "owner_of",
"..." : "..."
},
"relationships": {
"..." : "..."
}
}],
"links": {
"..." : "..."
},
"meta": {
"..." : "..."
}
}
Relation modeling in BEdita is expressed, as seen before, in {subject} {predicate} {object}
form wich is translated to {left object types} {relation name} {right object types}
on a left to right expression flow.
To achieve this we need to manipulate left and right side of the expression: both may contain a list of object types involved in the relation.
You may add object types to left side POST /model/relations/{{relation}}/relationships/left_object_types
and right side with
POST /model/relations/{{relation}}/relationships/right_object_types
.. http:post:: /model/relations/{{relation}}/relationships/left_object_types
{relation}
can be a numeric id of the relation, itsname
orinverse_name
Example request: add left object types:
POST /model/relations/owner_of/relationships/left_object_types HTTP/1.1
Host: api.example.com
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
{
"data": [
{
"type": "object_types",
"id": "3"
},
{
"type": "object_types",
"id": "2"
}
]
}
In this example users
(with _id_ 3) and profiles
(_id_ 2) have been added as left side object types to the relation created before.
Expected response is 200 OK
upon success, while response will contain only a "links"
section pointing to the list of left/right object types for the current relation.
To retrieve object types involved in a relation you can invoke GET /model/relations/{{relation}}/left_object_types
for the left side and
GET /model/relations/{{relation}}/right_object_types
for the right side.
{relation}
as usual can be a numeric id of the relation, its name
or inverse_name
and response will present a list of object types in "data"
section.
By invoking PATCH /model/relations/{{relation}}/relationships/left_object_types
you will replace all object types on the left side with a provided list. Same thing will happen with PATCH /model/relations/{{relation}}/relationships/right_object_types
.
.. http:patch:: /model/relations/{{relation}}/relationships/right_object_types
{relation}
can be a numeric id of the relation, itsname
orinverse_name
Example request: replace right object types:
PATCH /model/relations/owner_of/relationships/left_object_types HTTP/1.1
Host: api.example.com
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
{
"data": [
{
"type": "object_types",
"id": "13"
}
]
}
With this method we have completed our relation putting our custom object type seen in :ref:`api-model-object-types` on the right side.
Now we have: {users | profiles} {owner_of} {cats}
and inverse from right to left {cats} {belong_to} {users | profiles}
.
Expected response is 200 OK
upon success, while response will be contain only a "links"
section pointing to the list of left/right object types for the current relation.
To remove an object type from a relation you can call DELETE /model/relations/{{relation}}/relationships/left_object_types
(left side) or
DELETE /model/relations/{{relation}}/relationships/right_object_types
(right side) specifying an object type id in the request body.
.. http:delete:: /model/relations/{{relation}}/relationships/left_object_types
{relation}
can be a numeric id of the relation, itsname
orinverse_name
Example request: remove left object types:
DELETE /model/relations/owner_of/relationships/left_object_types HTTP/1.1
Host: api.example.com
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
{
"data": {
"type": "object_types",
"id": "2"
}
}
Here we have removed profiles
(_id_ 2) from the left side. Now our relation will look like {users} {owner_of} {cats}
.
Expected HTTP status response is 204 No Content
and an empty body is returned.
If object type is not a valid left/right type response will be 400 Bad Request
.
Operation is not allowed if an object of the type you want to remove is already used in the relation. A 403 Forbidden
error will be sent in this case.
You can modify a relation by using PATCH /model/relations/{relation}
endpoint.
.. http:patch:: /model/relations/{relation}
{relation}
can be a numeric id of the relation, itsname
orinverse_name
Example request: modify a relation:
In this example we will just change the description for the relation 1
PATCH /model/relations/owner_of HTTP/1.1
Host: api.example.com
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
{
"data": {
"id": 1,
"type": "relations",
"attributes": {
"description" : "Link users owning cats"
}
}
}
Response status 200 OK
expected upon success and complete modified relation is returned like in :ref:`api-model-relations-get`.
You can permanently delete a relation by invoking DELETE /model/relations/{relation}
.
This operation cannot be reversed and will not be allowed if actual object relations of this kind exist.
.. http:delete:: /model/relations/(relation)
{relation}
can be a numeric id of the relation, itsname
orinverse_name
Example request: delete relation:
DELETE /model/relations/owner_of HTTP/1.1
Host: api.example.com
Expected HTTP status response is 204 No Content
.
If relation is not found, response will be 404 Not Found
, if delete operation is not allowed a 403 Forbidden
will be sent.
HTTP/1.1 204 No Content