App Engine application for the Udacity training course.
- Update the value of
your-application-name
inapp.yaml
to the app ID you have registered in the App Engine admin console and would like to use to host your instance of this sample. - Update the values at the top of
settings.py
to reflect the respective client IDs you have registered in the Developer Console. - Update the value of CLIENT_ID in
static/js/app.js
to the Web client ID - (Optional) Mark the configuration files as unchanged as follows:
$ git update-index --assume-unchanged app.yaml settings.py static/js/app.js
- Run the app with the devserver using
dev_appserver.py DIR
, and ensure it's running by visiting your local server's address (by default localhost:8080.) - (Optional) Generate your client library(ies) with the endpoints tool.
- Deploy your application.
Explain in a couple of paragraphs your design choices for session and speaker implementation.
-
ConferenceSpeaker
is stored as its own model, independent of any user or conference. I chose to use it in this manner because speakers could present at different conferences, could eventually have ratings, previous conferences, future conferences etc; basically their own more comprehensive profiles. For now onlydisplayName
is in their model. -
ConferenceSession
is an entity model that inherits as a parent the conference for which it is created. I chose the parent inheritance because it becomes easier to query. The other option would have been to have a sessions field repeatedkeyProperty
onConference
, but that would have added more friction for removing sessions. Would have had the benefit of not having to query the db in order to retrieve all the sessions in a conference, but the downfall of storing an extra field of data. Either way :)
Think about other types of queries that would be useful for this application. Describe the purpose of 2 new queries and write the code that would perform them.
There are many queries that should potentially be added, I’ve implemented a different way of querying sessions when solving the query related problem (see below).
Qry 1: Get a speaker by name: Let’s say that a conference organizer registered a speaker for an earlier conference, now the organizer wants to use this speaker for a session, somehow she needs to get the speaker key and she only knows the name. Querying all speakers by name seems important.
conference.getSpeakerByName
Qry 2: Given a speaker and a conference return all sessions that have that speaker. Let’s say that a fanboy wants to attend all sessions from a certain speaker in a specific conference.
conference.getSessionsFromSpeakerAndConference
Let’s say that you don't like workshops and you don't like sessions after 7 pm. How would you handle a query for all non-workshop sessions before 7 pm? What is the problem for implementing this query? What ways to solve it did you think of?
Answer:
The query introduces the problem of two inequality filters. Since one inequality filter is searching for startTime > 19:00
and the seccond is type != workshops
which is executed with an OR
statement like: type < "workshop" OR type > “workshop”
.
There are a few ways to solve this problem:
-
Have a list of allowed
ConferenceSession
types likeallowed_types = [‘workshop’, ‘keynote’, ‘other’]
and query based on membership like:ConferenceSession.type.IN(allowed_types.remove(‘workshop’))
, this way the query becomes an equality query with OR like:ConferenceSession.type == ‘keynote’ OR ConferenceSession.type == ‘other’
:-
Drawbacks: If the list of allowed types is very large, the query becomes slower since it checks for a match in a large list.
-
Advantages: This will work well if we decide that
ConferenceSession.type
can be a repeated property (in case a session is both a workshop and something else), this way we can match multiple types.
-
-
Add a property
startTimeSlot
toConferenceSession
model which is computed based on the start time (eg: conference starts at 19:05 startTimeSlot is "19"(as in hour 19)), then like in the previous point make a list of allowed timeSlots and apply a membership filter removing the timeSlots that are not wanted (in this case removing[“19”,”20”,”21”,”22”,”23”]
). the filter will then look like:ConferenceSession.startTimeSlot.IN(allowedTimeSlots)
- whereallowedTimeSlots
is a list that includes all the possible timeslots for sessions within that conference on that day minus the unwanted times.-
Drawbacks:
-
it limits the specificity that a user is allowed to query by (eg if a user likes sessions that start at 7 but doesn’t like sessions after 7:30 his choices are limited to querying sessions either before 7 or before 8 and not before 7:30) - we could reduce the timeSlots to fit half hour blocks but that just opens up another problem with query speed since we’d be trying to match against a larger list.
-
adding a computed property after the application is running and there is existing data in the DB it requires extra legwork to update the model’s schema. The entities that don’t have the property computed need to be re-put.
-
-
Advantages:
- if done correctly we won’t need to worry about updating it in the future since most likely the 24 hour time measuring system is going to hold up for years to come :), unlike the previous example where we have to worry about loss of efficiency every time we add a new type of session.
-
I consider that out of the two, the first one would be better suited in this particular case because realistically there are only a few types of sessions and the field should be restricted to certain values anyway. Also allowing the inequality filter to be on the startTime
would enable us to order by time first which in my opinion makes more sense than ordering by session type first. In this project I implemented the startTimeSlot
purely because I thought it would be slightly more challenging :). (look for queryproblem
method in the conference api)
-
While both those solutions can be good in many cases, I believe the best solution in this case (the conference app), in terms of querying for sessions, is the Search API available in google app engine. This since one might want to run much more complex queries in different ways.
- Example: I want to know all sessions that talk about App Engine or Udacity (this would be in the highlights) that are not workshops and start before 11am or after 6pm, that are in programming conferences (this would be in the description of the conference) around San Francisco.
Since queries like this will take significant DB re-architecting, and a tremendous amount of time for figuring out all the potential indexes, creating a document for each session with the Search API seems to me like the best solution in this case. Even though search API queries are more expensive to run than NDB queries, I feel like the ability to return more relevant results quicker and reducing the development time when it comes to full text search within the DB is well worth it. :)
I have implemented this type of querying mechanism in
queryproblem2
in the conference api.
0.0.1
Apache License Version 2.0, January 2004
Free Software