5

I have struggled with the mongoose.model.populate function for hours now. I have even tried directly copying and pasting several solutions without luck.

I have a User model which is supposed to contain an array of 'Dilemmas' which he/she has created, but I have been unable to populate it.

Here are the models as well as the implementation of populate().

User.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

// Create Schema
const UserSchema = new Schema({
  username: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  date: {
    type: Date,
    default: Date.now
  },
  dilemmas: [
    {
      type: Schema.Types.ObjectId,
      ref: "Dilemma"
    }
  ]
});

module.exports = User = mongoose.model("User", UserSchema, "users");

Dilemma.js

const mongoose = require("mongoose");
const slug = require("mongoose-slug-generator");
const Schema = mongoose.Schema;
mongoose.plugin(slug);

// Create Schema
const DilemmaSchema = new Schema({
  creator: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User"
  },
  title: {
    type: String
  },
  slug: {
    type: String,
    slug: "title"
  },
  red: {
    type: String,
    required: true
  },
  blue: {
    type: String,
    required: true
  },
  red_votes: {
    type: Number,
    default: 0,
    required: true
  },
  blue_votes: {
    type: Number,
    default: 0,
    required: true
  },
  likes: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: "User"
      }
    }
  ],
  comments: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: "User"
      },
      text: {
        type: String,
        required: true
      },
      author: {
        type: String
      },
      avatar: {
        type: String
      },
      date: {
        type: Date,
        default: Date.now
      }
    }
  ],
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = Dilemma = mongoose.model("Dilemma", DilemmaSchema, "dilemmas");

Routes.js

// @route   GET api/users/profile
// @desc    Gets logged in user's profile
// @access  Private
router.get(
  "/profile",
  passport.authenticate("jwt", { session: false }),
  (req, res) => {
    User.find({ username: req.user.username })
      .populate("dilemmas")
      .then(user => {
        if (!user) {
          errors.nouser = "There is no user";
          return res.status(404).json(errors);
        }
        res.json(user);
      })
      .catch(err => res.status(400).json(err));
  }
);

JSON Response

[
    {
        "_id": "5b807beef770e7c7e6bf7ce0",
        "dilemmas": [],
        "username": "Jonas",
        "email": "[email protected]",
        "password": "$2a$10$QaqljS9x08YQ9N9EuCBTpO114ZJUFuVxAV80xMzImNi8eW2frPg0C",
        "date": "2018-08-24T21:43:10.411Z",
        "__v": 0
    }
]

JSON Dilemmas response

[
    {
        "red_votes": 0,
        "blue_votes": 0,
        "_id": "5b80975f6e47fecba621f295",
        "user": "5b807beef770e7c7e6bf7ce0",
        "title": "Am i the real author asdsdasd?",
        "red": "This is the red dilemma",
        "blue": "This is the blue dilemma",
        "likes": [],
        "comments": [],
        "date": "2018-08-24T23:40:15.381Z",
        "slug": "am-i-the-real-author-asdsdasd",
        "__v": 0
    },
    {
        "red_votes": 0,
        "blue_votes": 0,
        "_id": "5b808e789bc36bcae8c6c3ad",
        "creator": "5b807beef770e7c7e6bf7ce0",
        "title": "Am i the real author?",
        "red": "This is the red dilemma",
        "blue": "This is the blue dilemma",
        "likes": [],
        "comments": [],
        "date": "2018-08-24T23:02:16.565Z",
        "slug": "am-i-the-real-author",
        "__v": 0
    }
]

JSON Users response

{
    "_id": {
        "$oid": "5b807beef770e7c7e6bf7ce0"
    },
    "dilemmas": [],
    "username": "Jonas",
    "email": "[email protected]",
    "password": "$2a$10$QaqljS9x08YQ9N9EuCBTpO114ZJUFuVxAV80xMzImNi8eW2frPg0C",
    "date": {
        "$date": "2018-08-24T21:43:10.411Z"
    },
    "__v": 0
}
7
  • could you post your sample collections for both the documents Commented Aug 25, 2018 at 4:18
  • populate({path:"path",model:"model"}) Commented Aug 27, 2018 at 16:18
  • @AnthonyWinzlet, i have updated with the collections. Commented Aug 27, 2018 at 19:25
  • Can you try rendering the dilemmas in your View? I believe there is a known issue with populate() that the data does not show in the JSON although you can display it in a view. Commented Aug 27, 2018 at 19:30
  • @Michael, I guess I can try. I haven't created the view yet though, but I will let you know once i am done. Commented Aug 27, 2018 at 19:31

3 Answers 3

8

I just encountered a similar issue myself. Populating a ref worked, but populating an array of refs did not. I was able to get the array populate to work by explicitly specifying the model name in the populate call, e.g.:

User.find({ ... }).populate({
  path: 'dilemmas',
  model: 'Dilemma',
});

I don't know why this makes a difference, when the name of the referenced model is already specified in the schema.

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

Comments

0

Have you tried this?

User.find({ username: req.user.username })
  .populate("dilemmas")
  .exec() // <-- add exec() to perform the search
  .then(user => {
    ...
  })

4 Comments

Are you sure you have dilemmas in database for the user Jonas?
Yep, i actually posted the json response showing it, might have been edited out.
I'm asking this because the reponse JSON has an empty dilemmas array without any objectId in it
Yea, that is the whole problem. The JSON in the post is the response from the profile route, which is supposed to contain all the dilemmas created by the user. I have confirmed that there exists dilemmas in the database with an author ID of the same as the user
0

Did you check the documentation here?

https://mongoosejs.com/docs/populate.html#refs-to-children

It shows a similar setup (with Authors and Stories.) It mentions 'pushing' stories to be able to use a find / populate combo.

1 Comment

Yea, i read it earlier and tried to replicate what they had shown for my project. But nothing seems to work...

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.