MongoDB with Async Python Transcripts
Chapter: PyPI Beanie
Lecture: Creating the DB Models

Login or purchase this course to watch this video and the rest of the course contents.
0:00 So to create the Beanie models, which recall are really just Pydantic models with a couple of extras and a different base class,
0:09 we want to go and define that class. Now we could do this by hand, or we could come back to our friend JSON to Pydantic.
0:19 And we're just going to use this tool here because we want it to match exactly and it doesn't make that much sense for you to watch me go,
0:26 Oh, it was an underscore in the created date instead of no underscore, just the words together, things like that.
0:33 So what we're gonna do is we're gonna go to Studio 3T, grab the JSON representation and drop it over here and then convert it,
0:42 and then we'll actually do some editing on these classes. So step number one, get a rough representation to start with
0:48 so that we don't have to drudge through that. Let's go. Over here, notice we've got things that are actually not part of JSON.
0:58 We have this ISO date up here. This is great. We also, if you go, let's see another one, for example, object ID.
1:05 This is not a thing that is in regular JSON. So remember this JSON to Pydantic is not JSON to Beanie. It doesn't understand MongoDB things.
1:17 This is gonna say, this is a malformed JSON. So what we can do is we can come over here and say, customize the view to just show pure JSON,
1:26 which will help us with this. You can also just edit it by hand, it's not a huge deal. The other thing is, is we go through here,
1:33 you see there's multiple records. So let's just get one that we expect to be representative. So we'll just say limit one,
1:40 that way we can just come down here, Command + A, Command + C or Control + A, Control + C. Right, so this is gonna be the most complicated one,
1:48 this packages one. Let's put that in here first. Hello bar, goodbye bar. We give it a second and over here we've got our type.
1:57 So this model, this is actually what we're gonna call package, then this is our embedded piece here and then we have those, all right.
2:06 So I'm just gonna take these pieces, here's too many layers of scrolling and let's put that into a class.
2:16 Also notice that you can have it auto adjust your API, your names and so on there. If you're working with like a C# API or a JavaScript API
2:28 that has a different naming convention. Over to chapter eight, Beanie PyPI. I'm gonna make a folder here called models, lowercase models.
2:38 And that's where I'm gonna put these different classes. We could make a module called models, but I kinda wanna have it like this.
2:46 I really prefer, if you have taken my courses before, you'll know that I prefer to have one class per file
2:53 or really focused files and have more of them brought together. So that's what I'm doing. You do what you like. So this is gonna be Package, like that.
3:02 And we'll just do a paste. Now, notice I would rather type Pydantic for the moment here and import Pydantic.
3:13 Now, because Release is not a top-level object, it is actually an embedded object. Pydantic base model is the right type here.
3:25 This one is gonna be package and this is not gonna be a base model, right? It needs to be something that, for example,
3:32 brings in the queryability and the ID. So this is gonna be a Beanie document. And this docs URLs, a lot of times where we have any,
3:41 it's because it was null. So we want this to be optional, but it's not actually any, it's a string or it's optional.
3:48 Just because it's null, the Pydantic converter is like, you've given me no information, so this is what you get.
3:55 I'll say this is an optional of string. And let's go ahead and apply that to a couple. For example, this could be that way,
4:06 package URL, author name, especially the any. And this, in newer Python, we can use a lowercase list as of three,
4:15 and this is going to be a list of bson.objectId. That comes from MongoDB from PyMongo. And again, up here, this is going to be a dateTime.
4:26 We need to import that, datetime. That member datetimes, for whatever reason, don't exist in Java and JSON. So there's no way for it to know
4:36 that this could be a datetime, right? This is one of those bson upgrades, just like the objectId at the bottom here. And we have our list of release.
4:43 Okay, this is looking totally good again, int, int, int, create a date comment. This should be optional.
4:51 I think that's the only one that needs to be optional there. Excellent, so we've got everything working
4:57 for our most complicated part of our data model, the package and its nested embedded releases. Let's do the other two real quick
5:04 and we'll have these models put together. This one, we could do the limit one, But you know what? Not necessary.
5:15 Now again, notice it says invalid JSON for a second. Let's just turn that, tell them that's a string. So this is simple enough.
5:23 We could have typed it in ourself. This one, recall, was called release analytics. So we're just going to call the class name that as well. [no audio]
5:41 This should be a Beanie document. And it's going to be ReleaseAnalytics. The class, this we don't have to put here, right?
5:52 Explicitly this is handled by the base class, and this is an integer, so pretty simple, right? There it is. And finally, the last one we have is User.
6:02 Now, I know we modeled User again in the previous demos we've done, but I want to make sure it's an exact match, so let's just say limit 1.
6:12 And we'll just take this one, assume it's typical enough. Go in here. I'd use the simplified pure JSON view, so we'll take just that part there.
6:27 Again, this was null, so this is an optional.
6:44 But it's not just any, it's an optional string. Same there. And this is a beanie. The ID is done by itself, yes. It's called a user.
7:03 Email is fine. Hash password is going to be an optional string. Created date again is a date/time. This was a null. And this is a location.
7:18 Now, if maybe you weren't necessarily going to set a location, you could make this be
7:23 an optional location, but it looks like every record had it, so we're going to leave it like this here. And there it is.
7:29 We have our user with their embedded location. We have our package with its embedded release, and we have our release analytics because
7:39 we need to answer the question of how many packages there are, how many releases there are total, and that's just not something that we can simply do.
7:46 could do with the aggregation framework, but would it really be as fast as you want for something you might want to know all the time? Probably not.
7:55 So, we're just going to create this separate collection to store that little bit of data. And there it is.
8:02 Hopefully going through that process helped you a lot. I know it was a little bit repetitive perhaps, but going through it a couple times, showing
8:10 you how to actually bring all of that data over. We just did three collections. if you have a lot of different collections,
8:15 it's giving you a real clear roadmap and set of steps to make this happen in what I consider a pretty easy way.
8:22 There might be a mistake or two I haven't caught, hopefully not, like something that was specified as a string when it really should be an optional,
8:29 but we'll see about that. But I think we're pretty much there and we're ready to start doing some beanie with these models.


Talk Python's Mastodon Michael Kennedy's Mastodon