2

I have the following Schema with a array of ObjectIds:

const userSchema = new Schema({
    ...
    article: [{
        type: mongoose.Schema.Types.ObjectId,
    }],
    ...
},

enter image description here

I will count the array elements in the example above the result should be 10.

I have tried the following but this doesn't worked for me. The req.query.id is the _id from the user and will filter the specific user with the matching article array.

const userData = User.aggregate(
    [
        {
            $match: {_id: id}
        },
        {
            $project: {article: {$size: '$article'}}
        },
    ]
)
console.log(res.json(userData));

The console.log(article.length) give me currently 0. How can I do this? Is the aggregate function the right choice or is a other way better to count elements of a array?

4
  • 1
    Maybe your $match stage is returning any alement. Try to parse req.query._id to ObjectId Commented Aug 5, 2021 at 18:37
  • Thynk you for the comment. I have updated my answer and I tried a new aggregate function with the $project parameter. Do you know how I can display my $size variable? Commented Aug 5, 2021 at 18:47
  • 1
    await User.aggregate(...) Commented Aug 5, 2021 at 18:50
  • Yes thank you both. This helped me a lot now it is running. Thank you! Commented Aug 5, 2021 at 18:56

1 Answer 1

2

Not sure why to use aggregate when array of ids is already with user object.

Define articles field as reference:

const {Schema} = mongoose.Schema;
const {Types} = Schema;

const userSchema = new Schema({
    ...
    article: {
      type: [Types.ObjectId],
      ref: 'Article',
      index: true,
    },
    ...
});

// add virtual if You want
userSchema.virtual('articleCount').get(function () {
  return this.article.length;
});

and get them using populate:

const user = await User.findById(req.query.id).populate('articles');

console.log(user.article.length);

or simply have array of ids:

const user = await User.findById(req.query.id);

console.log(user.article.length);

make use of virtual field:

const user = await User.findById(req.query.id);

console.log(user.articleCount);

P.S. I use aggregate when I need to do complex post filter logic which in fact is aggregation. Think about it like You have resultset, but You want process resultset on db side to have more specific information which would be ineffective if You would do queries to db inside loop. Like if I need to get users which added specific article by specific day and partition them by hour.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.