Eve: Building RESTful APIs with MongoDB and Flask Transcripts
Chapter: Schema definitions and validation
Lecture: Data-relations and embedded resource serialization
Login or
purchase this course
to watch this video and the rest of the course contents.
0:01
One very special rule you have in your Eve arsenal is data relations.
0:05
Now, data relations don't really belong to the Mongo world,
0:10
in Mongo, you tend to use the subdocuments and sublists whenever possible
0:14
but there are situations where it still makes sense
0:17
to split data into different collections.
0:20
When you do that, Mongo doesn't offer you
0:23
a join feature like the SQL databases do.
0:27
You can achieve a similar result with the aggregation framework
0:31
which is also supported by Eve, by the way,
0:34
but the simple join between two documents
0:38
stored in different collections— that's a no-go.
0:41
Eve, however offers support for what we call embedded resource serialization.
0:48
It allows a client to request the reference of document
0:53
which are on different collections
0:55
to be returned as a subdocument.
0:58
So yes, with Eve data relations you're basically getting a join feature for free.
1:07
This is useful because this way
1:10
the client only has to perform one request to the remote server
1:14
whereas it will need two different ones.
1:18
To illustrate how data relations work in Eve I defined a new endpoint
1:23
let me close the people endpoint definition, and here we have works,
1:27
works has a schema and most of these fields are standard ones,
1:32
like title, which is a required string and description which is a string.
1:37
Let me close this one, let's look at owner.
1:41
Owner is of type objectid, it is required, and it also has a data relation.
1:49
So the reference at the resource is people
1:54
which means that an objectid in the owner field
1:59
is a reference to a document in the people collection with the same objectid.
2:05
It is also embeddable, which means that
2:08
clients are allowed to request as you can see in this example, here,
2:14
they are allowed to request the owner of this work to be embedded.
2:22
So let's go back to Postman and see these in action.
2:26
At the people endpoint that we have a number of authors,
2:30
let's take John Doe, for example, and copy his own id here.
2:35
Let's go and check the works endpoint.
2:40
It is empty, of course, let's try to post a new work,
2:46
something like a title, which might be My New Book,
2:55
description we'll skip it since it is not required.
3:00
but we want to add an owner
3:06
and the owner is going to be the id to John Doe,
3:09
It should be set, let's try this one, created, great.
3:14
So we got this in, let's try to hit the endpoint for this work,
3:25
Sorry, I need to perform a get request here,
3:28
Okay, my new book, and as you can see, owner is, off course, an id,
3:35
which is nice, useful, but a client now would need to go back to the remote server
3:42
and perform a request to the people endpoint for this author,
3:50
if it wanted to know who is the owner of this book or author.
3:56
So, what we can do here is, let me strip this a little bit,
4:03
is do something different.
4:12
So what I'm doing here is tell the API
4:15
hey send me this work here with this id,
4:19
but return the owner as an embedded document.
4:26
And here we go, as you can see now we get the title
4:30
and the owner is not a simple id anymore
4:33
it is actually a subdocument with the data coming from the people collection.
4:40
If I go back to the endpoint I can perform an embedded request here as well.
4:50
Now we only have one item in this collection
4:52
but as you can see here, if I had more than one work in the collection,
4:59
every single one would have a subdocument for the owner field.
5:04
Now this is a powerful and useful feature,
5:07
but it comes at a cost of course,
5:09
while the server is only receiving one request from the client
5:14
it is actually performing two requests on the database itself, as you can imagine
5:20
so when an embedded request comes in,
5:23
what happens is that Eve first retrieves the works document
5:28
and then goes and retrieves the owner
5:31
and builds an embedded document on the fly
5:35
before providing it back to the client.
5:38
Performance takes a hit here and you have to decide if it is worth it,
5:44
especially when clients are performing requests at the resource endpoint
5:49
like this one here, if we had, 1000 works in this collection
5:56
and every single document would require a double lookup
6:01
that would surely have a significant impact on your performance.
6:06
So you only want to enable embedding for fields where it really makes sense,
6:12
this is why it doesn't come by default,
6:15
you actually have to switch embeddable to true
6:18
if you want a client to be able to elevate a request to an embedded request.
6:24
Furthermore, you can disable embedding at any point
6:29
by simply setting the embedding to false, it is on by default,
6:39
it doesn't have any real impact until you switch the single fields on
6:44
by setting the embeddable option we saw before,
6:48
but you can switch off embedding totally
6:51
by just setting embedding = false.
6:54
Also, you can keep it enabled here at the global level
6:58
and then at the endpoint level, you can decide that,
7:06
for example, works can't be embedded.
7:12
So if you do these, even if the owner field below
7:17
within the schema is embeddable,
7:19
because of at the resource level,
7:22
embedding has been turned off,
7:24
the embedding request will be ignored.
7:27
Let's try that, let's save this new setting,
7:33
restart the server— oh, there is an error.
7:37
Oh, yes, of course, I'm not in C# here,
7:39
this is Python, so we need to do this, and back the client we go,
7:46
same request, embed query parameters is being ignored,
7:54
and this is because we switched embedding off for the works endpoint
7:59
If we had an embeddable field in the people collection,,
8:04
that one would still work, because by default,
8:06
embedding is enabled at a global level,
8:10
but works again were disabled locally.