LondonRob
LondonRob

Reputation: 78783

Correct way to seed MongoDB with references via mongoose

I have three schemas, one which references two others:

userSchema

{ name: String }

postSchema

{ content: String }

commentSchema

{ 
  content: String,
  user: { ObjectID, ref: 'User' },
  post: { ObjectID, ref: 'Post' }
}

How can I seed this database in a sane, scalable way? Even using bluebird promises it quickly becomes a nightmare to write.

My attempt so far involves multiple nested promises and is very hard to maintain:

User
.create([{ name: 'alice' }])
.then(() => {
    return Post.create([{ content: 'foo' }])
})
.then(() => {
  User.find().then(users => {
    Post.find().then(posts => {
      // `users` isn't even *available* here!
      Comment.create({ content: 'bar', user: users[0], post: posts[0] })
    })
  })
})

This is clearly not the correct way of doing this. What am I missing?

Upvotes: 1

Views: 3626

Answers (3)

Zhang Kai Yu
Zhang Kai Yu

Reputation: 362

If you want to seed database with automatically references, use Seedgoose. This is the easiest seeder for you to use. You don't need to write any program files, but only data files. And Seedgoose handles smart references for you. And by the way, I'm the author and maintainer of this package.

Upvotes: 2

radhey shyam
radhey shyam

Reputation: 769

Try this it will work fine:

Note: Node Promise.all will make sure that the both query is executed properly and then return the result in Array:[Users, Posts], If you get any error during execution of any query, it will be handle by catch block of the Promise.all.

let queryArray = [];
queryArray.push(User.create([{ name: 'alice' }]));
queryArray.push(Post.create([{ content: 'foo' }]));

Promise.all(queryArray).then(([Users, Posts]) => {
const comments = [
    { content: 'bar', user: Users[0], post: posts[0] }
];   
return Comment.create(comments);
}).catch(Error => {
   console.log("Error: ", Error);
})

Upvotes: 0

Alex Blex
Alex Blex

Reputation: 37048

Not sure about bluebird, but the nodejs Promise.all should do the job:

Promise.all([
    User.create([{ name: 'alice' }]),
    Post.create([{ content: 'foo' }])
]).then(([users, posts]) => {
    const comments = [
        { content: 'bar', user: users[0], post: posts[0] }
    ];    
    return Comment.create(comments);
})

Upvotes: 3

Related Questions