Lookup¶
Searching a database for useful information using the Mongo shell is difficult at best and requires knowing the MQL language. In this assignment, you'll create a web interface somewhat similar to the IMDB but pulling data from the WMDB.
In this assignment, you'll demonstrate command of the basics of Node/Express apps connecting to a MongoDB database (the WMDB). This is our first real web-database application!
- Processing parameterized GET requests
- Connecting to a database and making queries from Python
- Combining dynamic data with static templates to produce rendered pages
- Handling different routes
- Dynamically creating hyperlinks
- Using forms to get information from the user
Solution¶
To see an example of what you might build, you can look at
Alternatively, if there is any trouble with the previous link, you can try this:
lookup solution (flask version)
Note that the URLs on the deployed solutions have a prefix like
/lookup/
or cs304lookup/
; you should not do that.
Please don't feel that you have to present exactly the same interface that I do. I'm sure you can think of something more interesting, creative, or beautiful. Nevertheless, it exhibits the functionality I want.
Web Interface¶
The app will support these important URLs:
- To display the movie with TT = 456, the URL will be
/tt/456
- To display the person with NM = 123, the URL will be
/nm/123
-
To look up movies or people with a fragment of the name or title:
/search/?term=text&kind=movie/person
where term is the term (word) to search for, and movie/person indicates what kind of thing to search for.
In addition, the main page should have links to an example of a person and an example of a movie. Don't just use my example; use you and your partner's favorite!
The Lookup Routes¶
You have to implement four routes:
- something that displays a search form. I suggest using the
/
route for that. - a
/search/
route that processes the submitted search forms - a
/nm/<person_id_number>
route that shows the detail page for that particular person. - a
/tt/<movie_id_number>
route that shows the detail page for that particular movie.
You will not need to use POST in this assignment, since we are not updating the database, and POST is for updates. All routes will use GET.
Order¶
I strongly suggest that you proceed like this:
- Implement a
/nm/<person_id_number>
route that shows the detail page for that particular person. Skip the links to movies for now. - Test it by visiting
localhost:8080/nm/123
, substituting whatever port you are using. Do you see George Clooney's page? - Implement a
/tt/<movie_id_number>
route that shows the detail page for that particular movie. Skip displaying the cast for now. Test it withhttp://localhost:8080/tt/1454468
Do you see Gravity? - Improve that page by adding hyperlinks to the cast for
Gravity. Those will be links to
/nm/
routes, but those work now. - Improve the person detail page by adding links to their movies.
- Test that
Okay, now you're ready to display the form.
- Implement a dummy handler for processing a form. It should just
print the two values from the form to the console and return a
dummy result like
You submitted ${term} and ${kind}
- Create a partial file that has the form. Make sure the ACTION of the form is the URL for the dummy handler you just created.
- Include the partial file on the main page
- Implement a home route that renders the main page.
- Test that the form submits and has the information you need.
Finally, you're ready to process the form, which is last.
- The form submission handler gets the two pieces of information from
req.query
- It makes the appropriate query, getting a list of results.
- Print the result list to the console.
- Test that code.
- Add a conditional in the handler that looks at how long the list is.
- if the list is length zero, inform the user
- if the list is length one, redirect them to the appropriate detail page
- if the list is longer than one, print a list of hyperlinks to the various detail pages.
Movie Detail Page¶
The movie detail page must give the title of the movie in an H1
element with a class of title
. It must have a paragraph with the
title and release year. Then a list of the cast, with each name
hyperlinked to the person's page.
Person Detail Page¶
The person page must give the person's name in an H1 element with a class
of person
. It must also have a paragraph saying the name of the student
(staff member) who added that person, and when the WMDB person was
born. Then, it must have a list of the actor's movies (if any), each
hyperlinked to the movie page.
Note that the person page is a little more complicated than the movie page. You might start with the movie page.
Feel free to substitute the word person wherever I said actor, since
the people in the person
table are not always actors, though our focus
in this assignment is on actors, since we are listing the cast of a movie.
Depending on how you do your coding, the detail page for a person can
end up missing a lot of data, particularly if either they have no
films (maybe they are a director) or their addedby
field is null
(it shouldn't be, but it happens sometimes). Your coding should handle
those situations and at least give the person's name and birthdate (if
any).
Errors¶
If a person is not found, the page must say:
Sorry, no person with that ID is in the database
Similarly, if a movie is not found, the page must say:
Sorry, no movie with that ID is in the database
Multiple Matches¶
You should get the earlier stuff working first. Once it's working, add the partial your other pages (so that it appears on every page).
The handler must allow people to search by part of a person's name or part of a movie title. There are then three cases:
- No matches; report that situation, as specified above.
- Exactly one match; redirect to the detail page for that person or movie
- Multiple matches; render a page that lists all the matches, as hyperlinks to the detail page for that person/movie.
Strict API¶
Because I'll be doing semi-automated testing of your scripts, they need to have precise names and interfaces. Please use the URLs that I described above.
This strict API won't affect your coding much, if at all. Please, be creative in your appearance and the internals of your web app, not in the interface.
I'll be testing your code with URLs like these:
/
/nm/123
/search/?term=clooney&kind=person
/search/?term=george&kind=person
/tt/1454468
/tt/666
/search/?term=sally&kind=movie
/search/?term=harry&kind=movie
If you don't understand those URLs or what they should produce, please talk to me. You can also try them in my reference solution, above.
Getting Started¶
I suggest starting with the people
app. You can easily copy it to
your apps
folder like this:
cd ~/cs304/apps/
cp -rd ~cs304node/apps/people lookup
cd lookup
Testing Your Code¶
You should, of course, test your code to make sure that the kinds of URLs listed above work.
Hints¶
- Put a place on the main page to render error messages and supply
that value from the
res.render
function. If you use a conditional and supplynull
orfalse
when there's no error, there won't even be an empty container. - Formatting dates doesn't have to be hard. At first, just report the
YYYY-MM-DD pattern that the database has. When you're ready, you can
use the
new Date(string)
constructor to convert the date string into a date object. Then you can format it in a variety of ways, using the methods of the date object.
Advice¶
Everyone has their own habits for programming assignments, but here is some advice that you may find helpful. I found it useful to remind myself of these as I was coding the solution!
- Test your queries using the Mongo client or a cut-down script like we did with the Queries assignment, where it'll be easier see what kinds of results you'll get.
- Build in small increments. Don't sit down and code a complete solution right away. Code the smallest thing that you can test and then test it.
- Test often. As soon as you build a small chunk of the solution, test it and see if it works. Try to leave things in working order before you turn to other homework assignments.
- Look at the source of your HTML pages (the output of your scripts). Bugs there can be hard to track down if you're just looking at your JavaScript code.
- Using the HTML validator on the rendered source (use "view source" in your browser) sometimes helps
- Document as you go, so you'll know what works and what assumptions you're making.
- Take breaks. If you run into programming troubles that seem intractable, don't beat your head against it for hours. Take a break and come at it again when you're fresh. Sometimes that's all it takes to figure the problem out. We've all had that experience, I think.
Improved User Experience¶
As an incentive to spend a little time thinking about a beautiful as well as functional interface, you can earn up to 10 additional points for your interface. That's a pure judgment call on my part, based on nominations from the graders.
How you'll be graded¶
My policy for this programming assignment (and most programming assignments) is:
- 70 percent for functionality: does it work? do all the features work? all test cases passed?
- 10 percent for modularity and coding style
- 10 percent for documentation
- 10 percent for efficiency and other stuff
Specifically, I will look for:
- No global variables (constants are ok). This includes the database connection.
- Good modularity, function/variable names and parameter passing
- Good documentation
- Reasonable programming style. Lines shouldn't go beyond 80 characters
Please don't forget all the good programming techniques that you've learned in earlier classes. Look for appropriate abstractions and useful modules to reduce the redundancy and complexity of your code.
Don't forget to put your name(s) in a comment at the top of the file.
Turning the assignment in¶
The turn-in procedure for this:
- tar up the
lookup
folder intolookup.tar
- drop the
lookup.tar
file to the course account (see below) - Upload your code files to Gradescope, so that I can comment on them.
server.js
is the most important one, but your.ejs
files could be useful, too.
drop cs304node lookup.tar