Relationships

Introduction

In MongoDB, documents can have relationships with other documents (see MongoDB Relationships documentation section).

RESTHeart allows to declare the existing relationships in a collection, so that it automatically adds the links to related documents in its representation.

Declaring relationships adds the _links property to the documents only in the HAL representation format. This is not available in the default representation format. Add the query parameter ?rep=HAL to display the _links property.

The rels collection metadata

In RESTHeart, not only documents but also dbs and collections have properties. Some properties are metadata, i.e. they have a special meaning for RESTheart that influences its behavior.

The collection metadata rels allows to declare existing relationship so that links to the referenced documents are auto-magically included in the _link property

rels is an array of rel objects having the following format:

{
    "rel": "<relid>",
    "type": "<type>",
    "role": "<role>",
    "target-db": "<dname>",
    "target-coll": "<collname>",
    "ref-field": "<reffieldname>"
}
Property
Description
Mandatory
rel

Name of the relationship.

Yes
type Type of relationship: ONE_TO_ONE, MANY_TO_ONE, ONE_TO_MANY or MANY_TO_MANY Yes
role Role of the relationship: OWNING or INVERSE. This says where the reference field is. OWNING means it is in this document, INVERSE means that it is on the target document. Yes
target-db Database name of the referenced document(s)

No. If omitted the target db is supposed to be the current one

target-coll Collection's name of the referenced document(s) Yes
ref-field

Name of the first level field storing the id(s) of the referenced document(s) or the json path expression that resolves to the ids of the referenced documents (to reference nested fields).

The value of the first level field must be either the id string (in case the multiplicity of other side of the relationship is ONE) or an array of id strings (in case the multiplicity of other side of the relationship is MANY)

Note: json path expression must start with $, example:

$.a.nested.property will bind to {'a':{'nested':{'property':'docid'}}} and resolve to the value 'docid'

Yes

Examples

Tree of documents

In this example, we create a collection to store documents organized in a tree (each document has a single parent document).

Let’s create a collection, declaring a many-to-one relationship called parent, so that documents can refer a parent document in the collection itself.

PUT /parentcoll HTTP/1.1

{
    "rels": [
        {
            "rel": "parent",
            "type": "MANY_TO_ONE",
            "role": "OWNING",
            "target-coll": "parentcoll",
            "ref-field": "parent"
        }
    ]
}

HTTP/1.1 201 CREATED

Let’s now create few documents, specifying the parent property:

PUT /parentcoll/root HTTP/1.1

{"parent":"root"}

HTTP/1.1 201 CREATED
PUT /parentcoll/1 HTTP/1.1

{"parent":"root"}

HTTP/1.1 201 CREATED
PUT /parentcoll/1.1 HTTP/1.1

{"parent":"1"}

HTTP/1.1 201 CREATED
PUT /parentcoll/1.2 HTTP/1.1

{"parent":"1"}

HTTP/1.1 201 CREATED

If we now get the document /parentcoll/1.2, the _links property includes parent with the correct URI of the document /parentcoll/1

GET /test/parentcoll/1.2 HTTP/1.1

HTTP/1.1 200 OK
{
    "_id": "1.2",
    "parent": 1,
    "_links": {
        "parent": {
            "href": "/parentcoll/1"
        }
    }
}

One-to-Many, owning

In this example, we create two collections: bands and albums; of course, each band has a 1:N relationship to albums.

PUT /bands HTTP/1.1

{
	"rels": [{
		"rel": "albums",
		"type": "ONE_TO_MANY",
		"role": "OWNING",
		"target-coll": "albums",
		"ref-field": "albums"
	}],
	"descr": "music bands"
}

HTTP/1.1 201 CREATED
PUT /albums HTTP/1.1

{ "descr":"albums published by music bands" }

HTTP/1.1 201 CREATED

Let’s now create few albums:

PUT /albums/Disintegration HTTP/1.1

{"year":1989}

HTTP/1.1 201 CREATED
PUT /albums/Wish HTTP/1.1

{"year":1992}

HTTP/1.1 201 CREATED
PUT /albums/Bloodflowers HTTP/1.1

{"year":2000}

HTTP/1.1 201 CREATED

Now we create the band referring these albums:

PUT /bands/The%20Cure HTTP/1.1

{"albums":["Disintegration","Wish","Bloodflowers"]}

HTTP/1.1 201 CREATED

If we now get The Cure document, we can notice the albums link: /albums?filter={'_id':{'$in':['Disintegration','Wish','Bloodflowers']}}"

Since the other side of the relationship has cardinality N, the albums link is a collection resource URI with a filter query parameter.

GET /bands/The%20Cure HTTP/1.1

HTTP/1.1 200 OK
{
    "_id": "The Cure",
    "_links": {
        "albums": {
            "href": "/albums?filter={'_id':{'$in':['Disintegration','Wish','Bloodflowers']}}"
        },
    },
    "albums": [
        "Disintegration",
        "Wish",
        "Bloodflowers"
    ]
}

If we want to get the referenced document with httpie (or curl) we need to issue the following request:

GET /albums?filter="{'_id':{'$in':['Disintegration','Wish','Bloodflowers']}}"` HTTP/1.1

One-to-Many, inverse

We’ll resemble the previous example, but using an inverse relationship, i.e. the field storing the relationship will be stored in the album documents.

PUT /bandsi HTTP/1.1

{
    "rels": [
        {
            "rel": "albums",
            "type": "ONE_TO_MANY",
            "role": "INVERSE",
            "target-coll": "albums",
            "ref-field": "band"
        }
    ],
    "descr": "music bands"
}

HTTP/1.1 201 CREATED
PUT /albumsi HTTP/1.1

{ "descr":"albums published by music bands" }

HTTP/1.1 201 CREATED

Let’s now create few albums:

PUT /albumsi/Disintegration HTTP/1.1

{ "year":1989, "band":"The Cure" }

HTTP/1.1 201 CREATED
PUT /albumsi/Wish HTTP/1.1

{ "year":1992, "band":"The Cure" }

HTTP/1.1 201 CREATED
PUT /test/albumsi/Bloodflowers HTTP/1.1

{ "year":2000, "band":"The Cure" }

HTTP/1.1 201 CREATED

Now we create the band referred by these albums:

PUT /bandsi/The%20Cure HTTP/1.1

{"descr":"The Cure are an English rock band formed in Crawley, West Sussex, in 1976"}

HTTP/1.1 201 CREATED

If we now get “The Cure” document, we can notice the albums link: /albumsi?filter={'band':'The Cure'}

GET /test/bandsi/The%20Cure HTTP/1.1

HTTP/1.1 200 OK

{
    "_id": "The Cure",
    "_links": {
        "albums": {
            "href": "/test/albums?filter={'band':'The Cure'}"
        }
    },
    "descr": "The Cure are an English rock band formed in Crawley, West Sussex, in 1976"
}