Building data-driven web apps with Pyramid and SQLAlchemy Transcripts
Chapter: MongoDB edition
Lecture: Concepts: MongoEngine and MongoDB
0:00 Let's close out this chapter by reviewing
0:01 some of the concepts that we discussed
0:03 while going through our conversion
0:05 from SQLAlchemy to MongoDB.
0:07 First thing, we have to register connections
0:09 so pretty straight forward.
0:11 We just pass an alias in a name for
0:13 the database, and off it goes.
0:15 So here we said core, pypi_demo, and we
0:17 call MongoEngine.register_connection.
0:20 As long as our entities use the same alias
0:23 which is called db_alias in their little meta data thing
0:27 long as they use the same one, it just uses this connection.
0:29 Alright, it's kind of this ambient way to get to the database
0:32 so you don't have to go through that session stuff.
0:35 The classes that we map to the database derive from
0:38 a built-in base class mongoengine.Document.
0:42 Everything that's going to be saved to a
0:43 top level collection is a mongoengine.Document.
0:46 Here we have a package.
0:48 In this one, we're changing what the id is, like we did
0:51 we used the string instead of auto-incrementing id.
0:54 If we want to take a BSON, auto-generated BSON id
0:58 we can just omit that line
0:59 but this one we want to make sure it's a string
1:01 which is that unique, I guess we don't say unique here
1:04 we should say unique but that's a feature
1:07 but it's not one that we set.
1:08 Anyway, we want to make sure this is a unique thing
1:11 and that is just the name of the package.
1:14 And we have DatetimeField, StringField and so on.
1:16 Pretty straight forward.
1:18 What's really powerful though, is that we don't have to
1:20 limit ourselves to just tabular data.
1:23 We can have things like name, summary and homepage
1:25 that would be tabular, but then we can embed stuff.
1:28 Normally in a relational database, this takes other tables
1:31 to manage these many-to-many relationships.
1:33 Here we just have maintainers
1:35 and we're just embedding a list of items.
1:37 If we look at the record in the database
1:40 it looks like this.
1:41 We have our id, a date, the summary, and then we have
1:44 a bunch of maintainers that were put in there.
1:46 And this is just the id, this is like a relationship
1:49 back to the user table, cause it's many-to-many
1:51 we're not embedding users in here, right
1:54 but we can't avoid that maintainers table
1:56 that is the normalization table.
1:58 If you want to do a simple query, so easy.
2:00 Just package.objects(), column equals value
2:03 for direct equal, and you want one you say first()
2:05 if you want to do all of them, you just iterate over it
2:08 or you say .all(), things like that.
2:11 If you want to filter on one or more of the fields
2:13 if you want to filter on more than one and do an and
2:15 just comma separate them like any keyword arguments.
2:18 So in this case, the ID must match
2:19 the name of the past package name.
2:21 Like Request or SQLAlchemy.
2:24 We call first, and this actually triggers
2:26 the execution of the query.
2:29 If we didn't call that, we'd have to loop over it
2:31 or something, until then we could keep adding to it.
2:34 Now, it's going to return either one or None.
2:36 Let's imagine a world that we haven't been working in yet
2:40 that's a little bit more complicated.
2:41 We're doing a hotel, or Airbnb or something
2:44 and we have hotel rooms, those rooms have bookings
2:47 and the bookings store which guests are in them.
2:51 So we have a booking, object, it has an embedded object
2:55 called guest, that embedded guest object has an id.
2:58 If we want to answer the question of
3:00 show me all of the bookings for a given user
3:03 or given owner, we'd come through and say
3:05 go find that owner, going to do a simple query to get them
3:08 and then I can go to the room and say
3:10 go to the room's bookings, this double underscore
3:14 right there says, navigate the hierarchy.
3:17 We have bookings, a list of guests or something like that
3:22 or an embedded singular object called guest
3:24 and it has a guest id, so we're going into the
3:26 bookings list or embedded item.
3:29 So we go to the guest id, and then we want to do an
3:32 in query which is a list of IDs.
3:34 So find me all the bookings who have a guest
3:38 who is contained within the owners family IDs.
3:40 Pretty awesome that we can do this.
3:42 And the way you do it, is these double underscores
3:44 both navigate hierarchies, and they apply operators like
3:47 in, so __in, that's the operator
3:51 that's being applied in the query.
3:53 Now one of the patterns that I like to use
3:55 is make sure there's no data access outside this function.
3:59 We could return kind of a prepared query that's not
4:02 actually executed, and then if we run into an error
4:05 that error might happen in a view model
4:07 even maybe in a template.
4:08 So my sort of best practice for you is
4:11 to make sure all the data access is done
4:13 by the time you leave this function.
4:15 In this case a real easy way to do that is
4:16 convert this to an in-memory list.
4:19 That means the whole thing is exhausted
4:20 and we're not using data access anymore
4:22 we're just now working in memory.