Home > Net >  mongoose middleware, show length of array in model
mongoose middleware, show length of array in model

Time:06-30

I want to get the size of array in the model:

const UserSchema = mongoose.Schema(
  {
    username: { type: String, lowercase: true, required: true },
    items: { type: [mongoose.Types.ObjectId], default: [] },
  },
  {
    toJSON : {
      virtuals : true
    },
    timestamps: true,
  }
);


UserSchema.virtual("itemsCount").get(function () {
  return this.items.length;
});

module.exports = {
  UserModel: mongoose.model("user", UserSchema ),
};

const ProductSchema = mongoose.Schema(
  {
    name: { type: String, required: true },
    owner: { type: mongoose.Types.ObjectId,required: true, ref:"user" 
 },
  },
  {
    toJSON : {
      virtuals : true
    },
    timestamps: true,
  }
);


module.exports = {
  ProductModel: mongoose.model("product", ProductSchema ),
};

But I want to hide items in the output whenever I try to use projection it gives an error:

Cannot read properties of undefined (reading 'length')
const newPosts = await ProductModel.find({}).populate([{ path: "owner",  select: { itemsCount: 0 }}]);

if I don't use select it works:

const newPosts = await ProductModel.find({}).populate([{ path: "owner" }}]);

But I don't want to show items filed in output

CodePudding user response:

You can use aggregation pipeline for this:

ProductModel.aggregate([
  {
    "$lookup": {
      "from": "users",
      "localField": "user",
      "foreignField": "_id",
      "as": "users"
    }
  },
  {
    "$unwind": "$users"
  },
  {
    "$project": {
      _id: "$_id",
      name: "$name",
      "users": {
        itemsCount: {
          $size: "$users.items"
        }
      }
    }
  }
])

Read more about $lookup, $unwind, $project to understand.

Here is the Mongodb playground to see the results: https://mongoplayground.net/p/R0ZQiV8I-YM

  • Related