Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

NodeJS and MongoDB – use aggregate and $lookup together with findById

I want to make a relation between two collections – a book and author collections.
If i use only get and display all of my books and integrate the data about author by id it works.

Author schema:

 const AuthorSchema = new mongoose.Schema({
      name: { type: String, required: true },
      surname: { type: String, required: true },
      dateOfBirth: { type: String, required: true },
      countryOfBirth: { type: String, required: true },
      
    });

Book schema:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const BookSchema = new mongoose.Schema({
   owner: { type: String, required: true },
   pagesNo: { type: String, required: true },
   releaseDate: { type: String, required: true }, 
   country: { type: String, required: true },
   authorID: { type: Schema.Types.ObjectId, ref: "Author", required: true }, <-- HERE I NEED DATA ABOUT AUTHOR
});

My express function that works for fetching all data:

 router.get("/", async (req, res) => {
   try {
     let books = await Book.aggregate([
       {
        $lookup: {
          from: "authors",
          localField: "authorID",
          foreignField: "_id",
          as: "author",
        },
      },
    ]);

    res.status(200).json(books);
  } catch (err) {
    res.status(404).json({ success: false, msg: "Book is not found" });
  }
});

But now I want to display that joined data also when i search for a single book by ID (findById()).
I got an error status if I use a function like this:

router.get("/:bookId", async (req, res) => {
  try {
    let book= await Book.aggregate([
      {
       $lookup: {
              from: "authors",
              localField: "authorID",
              foreignField: "_id",
              as: "author",
            },
      },
    ]);
    book= book.findById({ _id: req.params.bookId});
    res.status(200).json(book);
  } catch (err) {
    res.status(404).json({ success: false, msg: "Book is not found" });
  }
});

Thank you for your help

>Solution :

use the $match to find only one book for the same query

const mongoose = require('mongoose');
const ObjectId = mongoose.Types.ObjectId();

    router.get("/:bookId", async (req, res) => {
          try {
            let book= await Book.aggregate([
              {
                $match: { _id : ObjectId("book _id") }
              },
              {
               $lookup: {
                      from: "authors",
                      localField: "authorID",
                      foreignField: "_id",
                      as: "author",
                    },
              },
            ]);
            book= book.findById({ _id: req.params.bookId});
            res.status(200).json(book);
          } catch (err) {
            res.status(404).json({ success: false, msg: "Book is not found" });
          }
        });
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading