Share
Explore

MONGO DB LAB Workbook: Movies and Actors: Creating Predicate Joins

Learning Outcomes:

Using $lookup to correlate various collections.

Step 1: Create a Database containing this Data:

Actors JSON:
[
{
"name": "Tom Cruise",
"age": 59,
"gender": "Male",
"movies": ["Mission: Impossible", "Jack Reacher", "Top Gun"]
},
{
"name": "Angelina Jolie",
"age": 46,
"gender": "Female",
"movies": ["Salt", "Mr. & Mrs. Smith", "Wanted"]
},
{
"name": "Jason Statham",
"age": 53,
"gender": "Male",
"movies": ["The Transporter", "Crank", "Spy"]
},
{
"name": "Charlize Theron",
"age": 45,
"gender": "Female",
"movies": ["Atomic Blonde", "Mad Max: Fury Road", "The Italian Job"]
},
{
"name": "Idris Elba",
"age": 49,
"gender": "Male",
"movies": ["Luther", "Hobbs & Shaw", "The Dark Tower"]
},
{
"name": "Scarlett Johansson",
"age": 36,
"gender": "Female",
"movies": ["Black Widow", "Lucy", "Ghost in the Shell"]
},
{
"name": "Chris Hemsworth",
"age": 38,
"gender": "Male",
"movies": ["Extraction", "Thor", "Men in Black: International"]
},
{
"name": "Emily Blunt",
"age": 38,
"gender": "Female",
"movies": ["Edge of Tomorrow", "Sicario", "The Girl on the Train"]
},
{
"name": "Matt Damon",
"age": 50,
"gender": "Male",
"movies": ["The Bourne Identity", "Elysium", "The Martian"]
},
{
"name": "Gal Gadot",
"age": 36,
"gender": "Female",
"movies": ["Wonder Woman", "Fast & Furious", "Keeping Up with the Joneses"]
}
]


Movies JSON:
[
{
"title": "Mission: Impossible - Fallout",
"year": 2018,
"genre": ["Action", "Adventure", "Thriller"],
"actors": ["Tom Cruise", "Rebecca Ferguson", "Henry Cavill"]
},
{
"title": "Salt",
"year": 2010,
"genre": ["Action", "Mystery", "Thriller"],
"actors": ["Angelina Jolie", "Liev Schreiber", "Chiwetel Ejiofor"]
},
{
"title": "The Transporter",
"year": 2002,
"genre": ["Action", "Crime", "Thriller"],
"actors": ["Jason Statham", "Qi Shu", "Matt Schulze"]
},
{
"title": "Atomic Blonde",
"year": 2017,
"genre": ["Action", "Mystery", "Thriller"],
"actors": ["Charlize Theron", "James McAvoy", "John Goodman"]
},
{
"title": "Luther",
"year": 2010,
"genre": ["Crime", "Drama", "Mystery"],
"actors": ["Idris Elba", "Dermot Crowley", "Michael Smiley"]
},
{
"title": "Black Widow",
"year": 2021,
"genre": ["Action", "Adventure", "Sci-Fi"],
"actors": ["Scarlett Johansson", "Florence Pugh", "David Harbour"]
},
{
"title": "Extraction",
"year": 2020,
"genre": ["Action", "Thriller"],
"actors": ["Chris Hemsworth", "Rudhraksh Jaiswal", "Randeep Hooda"]
},
{
"title": "Edge of Tomorrow",
"year": 2014,
"genre": ["Action", "Sci-Fi"],
"actors": ["Emily Blunt", "Tom Cruise", "Bill Paxton"]
},
{
"title": "The Bourne Identity",
"year": 2002,
"genre": ["Action", "Mystery", "Thriller"],
"actors": ["Matt Damon", "Franka Potente", "Chris Cooper"]
},
{
"title": "Wonder Woman",
"year": 2017,
"genre": ["Action", "Adventure", "Fantasy"],
"actors": ["Gal Gadot", "Chris Pine", "Robin Wright"]
}
]


Write MONGODB code to list all the movies that Tom Cruise is in:
db.movies.find({ actors: "Tom Cruise" })
Student Exercise:
Extend this to using regex and wildcards, $gt, $lt

Correlate between the collections: Write db shell code to list all movies with a female actress
To list all movies with a female actress, you can use MongoDB's $lookup aggregation pipeline stage to join the movies collection with the actors collection based on the actors field.
db.movies.aggregate([
{
$lookup: {
from: "actors",
localField: "actors",
foreignField: "name",
as: "actorsInfo"
}
},
{
$unwind: "$actorsInfo"
},
{
$match: {
"actorsInfo.gender": "female"
}
}
])

This code first performs a $lookup stage to join the movies collection with the actors collection.
The from field specifies the collection to join with,
localField specifies the field in the movies collection to match on (actors),
foreignField specifies the field in the actors collection to match on (name),
as specifies the name of the new field to add to the documents in the movies collection (actorsInfo).
The $unwind stage then flattens the actorsInfo field to create one document for each actor in the actorsInfo array.
Finally, the $match stage filters the results to only include documents where the actorsInfo.gender field is "female". This will return all movies that have at least one female actress.

Write Mongoose code to do all steps
(1) import the actors and movies collections from text files
(2) find movies with actor Tom Cruise
(3) do correlate between the collections with mongoose code to list all movies with a female actress

Here's the Mongoose code to do all of these steps:
To fix the error, you need to remove the callback function and use async/await instead. The updated code should look like this:


const mongoose = require('mongoose');
const fs = require('fs');

// Connect to MongoDB
mongoose.connect('mongodb://localhost/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });

// Define schema for actors collection
const actorSchema = new mongoose.Schema({
name: String,
gender: String,
age: Number
});
const Actor = mongoose.model('Actor', actorSchema);

// Define schema for movies collection
const movieSchema = new mongoose.Schema({
title: String,
year: Number,
genre: [String],
actors: [String]
});
const Movie = mongoose.model('Movie', movieSchema);

// Import actors and movies collections from text files
const actorsData = fs.readFileSync('actors.json', 'utf8');
const actors = JSON.parse(actorsData);

const moviesData = fs.readFileSync('movies.json', 'utf8');
const movies = JSON.parse(moviesData);

(async () => {
try {
await Actor.insertMany(actors);
console.log('Actors imported successfully');
} catch (err) {
console.error(err);
}

try {
await Movie.insertMany(movies);
console.log('Movies imported successfully');
} catch (err) {
console.error(err);
}

try {
const moviesWithTomCruise = await Movie.find({ actors: 'Tom Cruise' });
console.log('Movies with Tom Cruise:', moviesWithTomCruise);
} catch (err) {
console.error(err);
}

try {
const moviesWithFemaleActresses = await Movie.aggregate([
{
$lookup: {
from: 'actors',
localField: 'actors',
foreignField: 'name',
as: 'actorsInfo'
}
},
{
$unwind: '$actorsInfo'
},
{
$match: {
'actorsInfo.gender': 'female'
}
}
]);

console.log('Movies with female actresses:', moviesWithFemaleActresses);
} catch (err) {
console.error(err);
}
})();

By using async/await and wrapping the code in an async function, you can properly handle the promise-based operations.

This code first connects to the MongoDB database with Mongoose.
Then, it defines Mongoose schemas for the actors and movies collections.
Next, it reads the data from the actors.txt and movies.txt files, parses the JSON data, and inserts the data into the corresponding collections using Mongoose's insertMany() method.
After that, it uses Movie.find() to find all movies that have the actor "Tom Cruise".
Finally, it uses Movie.aggregate() with the $lookup stage to join the movies collection with the actors collection, and the $match stage to filter the results to only include movies with female actresses.

Next Steps: Using this Template code: Implement your Project:
Write your Project’s Datastore. Upload it to Atlas.
Create a Web Server front end using Express.js. Use routing end points and web forms using the methods from MAD 6135 to allow Web Browser Access (CRUD) to your Datastore to implement your Project’s Use Cases.
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.