Building data-driven web apps with Pyramid and SQLAlchemy Transcripts
Chapter: MongoDB edition
Lecture: Rewriting our queries
0:00 We saw our site doesn't work
0:01 because we're trying to access SQLAlchemy
0:04 which we're no longer configuring in our
0:07 various data services, so now what we're going to do
0:09 is go rewrite these data services
0:11 like this last latest releases.
0:14 It might sound challenging, but it turns out
0:16 to be super easy, let's go do it.
0:18 Here's part of that design pattern thing I spoke about.
0:20 We've taken every single bit of data access
0:23 and we've isolated it down into just these two modules
0:28 a couple of functions within each.
0:30 So that means, within the view models
0:32 within the controller methods, all of that stuff
0:35 none of them care about the details
0:38 of how we talk to the database
0:39 they just expect classes back.
0:41 And as long as the classes have
0:42 the right type, it'll be okay.
0:44 So, that's the beauty right here.
0:46 Let's go down, and all we have to do
0:48 is rewrite these queries, rewrite how
0:51 we get package count, for example.
0:53 So let's get to it, it's going to be really quick.
0:55 We're going to change this to nosql.
0:58 We don't use this unit of work pattern for MongoEngine.
1:01 I do kind of like the unit of work pattern
1:03 but they don't use it, so here we go.
1:05 Now instead of going and creating the query on a session
1:08 we go to the class and we say objects.
1:11 Now this is just a blank query
1:13 there's not filters and stuff, but we could put those here.
1:17 Okay, so that's going to do that one, let's do Release.
1:19 This is going to do ...
1:24 Okay, not too hard so far.
1:26 That's one's kind of the hardest one
1:28 so let's put that away for a minute.
1:30 So this one kind of looks complicated.
1:32 Remember the joins and all that.
1:35 So we're going to find a package by name
1:36 so we go to the package, and go to it's objects
1:39 now we can .. the filter does work
1:41 exactly like this, but what we can do is
1:43 if we're just doing one filter
1:45 we can just put that ... right there.
1:47 We don't need this filter statement.
1:49 OK, so it's kind of equivalent.
1:50 The other thing that's different
1:52 is we don't use double equal, we use single equal
1:55 and then we don't use the type, we just say the field.
1:57 Okay, so it's just id is that.
1:59 At this point, we can make this
2:00 look a lot cleaner, like that.
2:02 That's pretty slick.
2:03 Alright, we got one more down here.
2:06 We want to go to create a list of the results of this query.
2:11 Objects and then we're going to get the limit
2:14 by whatever that value is.
2:16 Look at this, this is comin' along pretty easy, right?
2:19 Now, finally, this one here.
2:21 So we want the releases ...
2:26 Objects ... Order by ...
2:28 Also exists in MongoEngine, but this
2:30 syntax doesn't exist.
2:31 If you want to sort by this field
2:35 descending, you just put it as
2:36 a string with a minus in the string.
2:38 I don't like that as much, but that's how it works.
2:41 That's it, this one's done, and then down here, again
2:44 we're going to go to our package
2:46 it's going to be .objects()
2:50 and this one gets pretty interesting.
2:51 See how we're doing this query of
2:53 I like the ID to be contained within this set?
2:56 Same idea in MongoDB, but it's going to go like this.
3:00 Say id instead of dot, you do id__in
3:03 to apply the operator and you don't have the ... there
3:06 and you just say equal the set.
3:08 Different, not super hard.
3:09 I think, I think this might do it.
3:11 This may well do it.
3:12 Let's run and see what happens.
3:14 Now we didn't change the user thing
3:15 so that might, that might pose a problem, let's find out.
3:20 None type is callable.
3:21 Where is this?
3:22 Yep, user service, user count, okay.
3:25 We got to do that over here.
3:26 I think just the one, so, instead of data
3:28 we'd have nosql, we don't have unit of work
3:32 we have .objects(). Let's try again.
3:36 I think that might be enough to make it run.
3:39 Boom, look at that, it's working! Like a champ.
3:42 If I login there's going to be some minor issues.
3:44 We don't have our data yet, but it's great.
3:46 We can even come over here and try to get to a project.
3:49 ike request, it's not in the database
3:51 so it should 404, right?
3:53 Perfect, didn't crash, it went to the database
3:55 said eh, not here, 404.
3:57 Of course it's not here 'cause the database is empty.
3:59 We're going to solve that problem in a minute
4:00 but this, this is pretty awesome.
4:02 We now have our stuff converted.
4:04 Let's go ahead and finish out this user stuff here.
4:07 Turns out there's just a few steps left.
4:09 Okay, remember, create the user, all good.
4:12 Instead of all of this, you just say user.save().
4:17 So here we're going to do a query
4:18 for the user by email, actually
4:21 we have a little function below called
4:23 find_user_by_email, let's just re-use that.
4:27 I think, it's going to do this as well.
4:30 Alright, that's pretty easy.
4:33 It's not, but it will now.
4:39 So again, we don't do it this way
4:41 we go and say .objects()
4:44 and we don't use the type name
4:46 we do assignment like so. That's it.
4:48 We have now entirely re-written our app.
4:52 100 percent, to move from SQLAlchemy to MongoDB
4:57 using MongoEngine, period, done, that's all of it.
5:00 And, most importantly, notice we've only changed
5:03 these two files that are focused on data access.
5:06 Granted, we had to add these, because, well
5:09 you can't have the entities without adding them
5:11 but it's not like we re-wrote a
5:13 whole bunch of stuff up here.
5:14 Notice, no color changes in this implementation.
5:17 Down in the view models, there's tons of them
5:20 all over the place, no changes.
5:23 Because we implemented this beautiful
5:25 little pattern of hiding our data access
5:27 here, and then exchanging classes.
5:29 Now, there's little tiny issues going on.
5:32 Like, let's see if we can find one, maybe this one.
5:36 No, I was thinking maybe some of them import.
5:40 pypi.data.user, and things like that
5:43 for, like type-ins, but they're not even doing that.
5:46 If they did, we'd just change it
5:47 I've chosen these to be exactly
5:49 at least really really close in terms of names
5:53 of the columns and stuff, so that
5:55 it really doesn't matter which one you say it is
5:57 but it's better to have it correct, of course.
6:00 Almost works. There's one ultra small problem
6:03 well, first, the data's not there
6:05 but there's one other small problem that we got to fix.
6:08 It's going to require us to change the base ViewModel
6:10 so, this thing I told you about, the beauty
6:12 there's one tiny detail, and the detail
6:14 is because, over here, the user is using the default id
6:19 which is what's called an ObjectId
6:22 whereas in this one, it's using an integer.
6:25 The cookie handling needs to be
6:28 slightly adjusted to deal with that.
6:30 No problem there.