Aggregation Pipeline Returning Empty Array

Hello everyone,

I am encountering an issue where an aggregation query is returning an empty array, even though I expect it to return matching documents from my collection. Here’s the relevant portion of my code:

if (useShuffle) {
  cards = await Card.aggregate([
    {
      $match: { collectionId: collectionId },
    },
  ]);
}
  • When running the code, I receive an empty array, even though there are documents with this collectionId in the database.

I have verified that the value of collectionId is correct and matches the documents in the collection. However, the aggregation still returns an empty array. When I use a regular find query, it works fine:

const cards = await Card.find({ collectionId: collectionId });

What could be causing this issue? Any insights would be greatly appreciated!

Thank you in advance.

1 Like

This is quite abnormal.

If

works, then

should work.

May be useShuffle is false and the aggregation is not even called.

The call to aggregate() returns a cursor. Do you call toArray() or something similar to get the documents from the cursor?

I have also tried using:

cards = await Card.find({ collectionId });

in the useShuffle condition, and it returned the expected data. So, the issue doesn’t seem to be with the condition itself.

I tested the query with another field, like userId, and it returned data correctly.

Your tests then eliminate issues with code logic. Good.

This last observation points to the direction of type mismatched between the stored value and the runtime type of the variable collectionId. For example, if the collectionId field is stored as a number, then the runtime type of the variable collectionId must also be a number. A frequent error, is that we get the variable value from a HTML form and the values are strings unless converted.

So what I suspect is that you do not obtain the value of collectionId using the same mean in the find vs the aggregate case. So it works with find because the runtime type of collectionId is correct while it is not correct for aggregate. For example, it could be the case that for find you do:

and for aggregate you do:

Something like

might be sufficient to make it work.

Hi @Abdulrahman_almuhajir,

Since your code is JavaScript, I assume you are using Mongoose as a client.

I assume that collectionId is a reference to a document in another collection (ObjectId).

When you perform a find() query, Mongoose will automatically convert your string to ObjectId.

However, when you perform aggregate() query, you need to cast your string yourself, in order for the query to work.

So, I suggest that you try the following:

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

...

cards = await Card.aggregate([
  {
    $match: { collectionId: ObjectId(collectionId) },
  },
]);
1 Like

@Abdulrahman_almuhajir, could you please confirm if you are using Mongoose or not?

I moved your thread to Working with Data since your issue is not Atlas specific. I also add the tag mongoose-odm because NeNaD’s reply makes a lot of sense and it is a potential source of type mismatch.

Please try the suggestion

and if it works please mark NeNaD’s post as the solution.

1 Like