MongoDB Aggregate vs. Query Example


Updated May 4th, 2022

Task: Need to leverage a given “username” to look up the “_id” of a user in a “users” collection. Then use that “_id” to find all documents in a “cars” collection where the “_id” from the “users” collection matches the “authorId”

Code with Aggregate:

const usersCollection = client.db().collection("users")
      let cars = await usersCollection
          // look up id from users given the username
          { $match: { username: username } },
          { $lookup: { from: "cars", localField: "_id", foreignField: "authorId", as: "carDocument" } },
          { $unwind: "$carDocument" },
            $project: {
              _id: 1,
              username: 1,
              useful_miles: 1,
              monthly_miles: 1,
              // kind of merge the two together
              carId: "$carDocument._id",
              authorId: "$carDocument.authorId",
              description: "$carDocument.description",
              price: "$carDocument.price",
              miles: "$carDocument.miles",
              link: "$",
              createdDate: "$carDocument.createdDate"


    username: 'pepper',
    useful_miles: 150000,
    monthly_miles: 1250,
    cars: {
      authorId: new ObjectId("62728d8c6f59729aaf25f53d"),
      description: '2017 Honda HR-V EX AWD',
      price: 17250,
      miles: 73516,
      link: '',
      createdDate: 2022-05-04T14:28:28.420Z

Some notes on the aggregate:

Is there a way to run the “toString” method on the “authorId” property to prevent getting the new ObjectId? (Cannot just add “$carDocument._id.toString()” or the propoerty will not be output at all. See docs for a possible solution).

The “$unwind” property is used to only re-spell out as a nested object. You can alternatively just have all on one level.

Code with Query

const usersCollection = client.db().collection("users")

      const sessionDoc = await usersCollection.findOne({ username: username })
      let sessionId
      if (!sessionDoc) {
        throw "no session doc"
      sessionId = sessionDoc._id.toString()

      const carsCollection = client.db().collection("cars")

      const cars = await carsCollection.find({ authorId: new ObjectId(sessionId) }).toArray()

Output of Query Code

    _id: new ObjectId("627299c16f59729aaf25f53e"),
    authorId: new ObjectId("627267346f59729aaf25f539"),
    description: '2017 Honda HR-V AWD',
    price: 17250,
    miles: 73516,
    link: '',
    createdDate: 2022-05-04T15:20:32.130Z
    _id: new ObjectId("627299dd6f59729aaf25f53f"),
    authorId: new ObjectId("627267346f59729aaf25f539"),
    description: '2017 Chevy Equinox LT FWD',
    price: 15792,
    miles: 81860,
    link: '',
    createdDate: 2022-05-04T15:21:00.914Z

Some notes on the query

Need two steps to get the data, 1.) findOne on users collection and 2.) use find on the cars collection.

Need to return two things into one object manually.


Run one with aggregate but I don’t want the user data on every document, although I do need it.

How to Measure Which is Better?

Is there a metric, (Big O)?