Skip to content
Related Articles

Related Articles

Improve Article

MongoDB lookup using Node.js

  • Last Updated : 14 Jun, 2021

The $lookup operator is an aggregation operator or an aggregation stage, which is used to join a document from one collection to a document of another collection of the same database based on some queries. Both the collections should belong to the same databases.

Aggregation in MongoDB is an operation that groups values from multiple documents together and can perform a variety of operations on the grouped data to return a single result. And $lookup is one of the operations which aggregation performs.

How $lookup works?

We have two collections, input collection (the collection on which $lookup is performed) and from collection (the collection from which we take documents to join it to documents of input collection).

$lookup takes selected documents from the “from collection” based on some queries and then attaches them to the document of “input collection” in a separate array field. It is just like a left outer join of SQL.

Perform $lookup with Equality Match:

In equality match, for each document, the value of any specific field of input collection document is compared with the value of any specific field of every from collection document and if they get matched, that particular from collection document is attached to the input collection document in a separate array field.



Syntax: $lookup operator

{
    $lookup:
    {
        from: < "from collection" >,
        localField: < any field from "input collection" >,
        foreignField: < any field from "from collection" >,
        as: < attached array field >
    }
}
  • from: It is the field that contains the name of “from collection“, from which the documents are to be taken to join them to the documents of the input collection.
  • localField: It is any field of input collection the value of which is to be compared which the foreignField value.
  • foreignField: It is any field of from collection the value of which is to be compared which the localField value.
  • as: It is the array field in which the matched documents of from collection are to be stored.

Install Mongoose:

Step 1: You can visit the link Install mongoose to install the mongoose module. You can install this package by using this command.

npm install mongoose

Step 2: Now you can import the mongoose module in your file using:

const mongoose = require('mongoose');

Database: We have already created collections named orders and customers in our database GFG with the following entries show in the image below:

Collections orders and customers in database GFG

Creating a Node application:

Step 1: Create package.json using the following command:

npm init

Step 2: Create file model.js which contains Schema and Model for orders and customers collections.

model.js




const mongoose = require('mongoose');
  
const orderSchema = new mongoose.Schema({
    _id: Number,
    customerId: Number,
    itemName: String
})
  
const customerSchema = new mongoose.Schema({
    _id: Number,
    name: String,
    city: String
})
  
const Order = new mongoose.model('order', orderSchema);
const Customer = new mongoose.model('customer', customerSchema);
  
module.exports = { Order, Customer };

 



Step 3: Create file main.js with the following code.

main.js




// Requiring module
const mongoose = require("mongoose");
  
// Importing Models Order and Customer from model.js
const { Customer, Order } = require("./model");
  
// Connecting to database
mongoose.connect("mongodb://localhost:27017/GFG", {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  useFindAndModify: false,
});
  
// Implementing $lookup for customers collection
Customer.aggregate([
  {
    $lookup: {
      from: "orders",
      localField: "_id",
      foreignField: "customerId",
      as: "orders_info",
    },
  },
  // Deconstructs the array field from the
  // input document to output a document
  // for each element
  {
    $unwind: "$orders_info",
  },
])
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.log(error);
  });

Run main.js using the command:

node main.js

Explanation: Here each customers collection documents _id field value is compared with each orders collection document’s customerId field , and if they get matched , that orders collection document is attached to the customers collection document in orders_info array field.

Note: Here $unwind is used to deconstructs the “orders_info” array field from the input document to output a document for each element. With this we will be able to see each attached document.

Output: In the console, we are getting input collection documents after joining from collection documents with them using $lookup.

Output after executing main.js

When we will eliminate $unwind operator from the code, we will get output as shown below:

Output without using $unwiind operator

Performing $lookup with multiple  join conditions:

Syntax : $lookup operator

{
$lookup:
{
from: < “from collection” >,
let: { < var_1 >: < field_1 > , < var_2 >: < field_2 > , …… },
pipeline: < different pipeline stages to be performed of “from” collection >,
as: < attached array field >
}
}

  • from: It is the field which contains the name of “from collection”, from which the documents are to be taken to join them to the documents of the input collection.
  • let: It is an optional field. Pipeline cannot directly access “input” documents fields , therefore in let variable we define names for the input document fields to be used in pipeline for performing queries.
  • pipeline: It is the field which runs different stages of pipeline on documents of “from” collection and then returns the resulted documents in the array field.
  • as: It is the array field in which the matched documents of from collection are to be stored.

 



Note:

  • To use variables defined in $let field, we reference it like $$<variable>.
  • Use $expr operator inside $match, to access variables $let field.

Change main.js file as given below and run to get the result:

main.js




const mongoose = require("mongoose");
  
// Model for Order and Customer
const { Customer, Order } = require("./model");
  
// Connecting to database
mongoose.connect("mongodb://localhost:27017/GFG", {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  useFindAndModify: false,
});
  
// Performing multiple query with the help of pipeline
Customer.aggregate([
  {
    $lookup: {
      from: "orders",
      let: { custId: "$_id" },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $eq: ["$customerId", "$$custId"] },
                { $eq: ["$itemName", "Watch"] },
              ],
            },
          },
        },
      ],
      as: "orders_info",
    },
  },
  {
    $unwind: "$orders_info",
  },
])
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.log(error);
  });

Run main.js using command:

node main.js

Explanation: In the above code, we are joining documents from orders collection whose value of customerId matches with the value of _id of customers collection and whose value of itemName is “Watch”. To use _id field of customers collection in pipeline we have defined it as custId in let field.

Note: Here $unwind is used to deconstructs the “orders_info” array field from the input document to output a document for each element. With this we will be able to see each attached document.

Output : In the console, we are the getting matched documents as shown below:

Output after executing main.js

When we will eliminate $unwind operator from the code, we will get output as shown below:

Output after eliminating $unwind operator




My Personal Notes arrow_drop_up
Recommended Articles
Page :