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