2

I am new with MongoDB "relations" and I am trying to save data to a MongoDB database. There are two models, one model is the user and the other model is the authentication data. The data is saved correctly.

import { Schema, model } from 'mongoose'

const stringRequired = {
  type: String,
  trim: true,
  required: true
}

const stringUnique = {
  ...stringRequired,
  unique: true
}

const UserSchema = new Schema({
  name: stringRequired,
  username: stringUnique,
  email: stringUnique,
}, { timestamps: true });

const AuthSchema = new Schema({
  email: { type: Schema.Types.ObjectId, ref: 'User' },
  salt: stringRequired,
  hash: stringRequired,
}, { timestamps: true })

export const userModel = model('User', UserSchema)
export const authModel = model('Auth', AuthSchema)

As you can see, one of the models is referenced by another. The email field has a reference to the user, email being the id that I want to use for authentication. But for some reason, when I save the documents, all the data is sent except the reference.

This is my controller, which as you can see, abstracts the user and the authentication to carry out the business logic and then save it in the database separately.

function add(body: any) {
    return new Promise((resolve, reject) => {
      if (!body) {
        const error = new Error('No body on the request')
        reject(error)
      } else {
        const user = {
            username: body.username,
            email: body.email,
            name: body.name
        }

        const saltRouds = 10
        const salt = bcrypt.genSaltSync(saltRouds)
        const hash = bcrypt.hashSync(body.password, salt)
        const auth = { salt, hash }

        store.add(userModel, user)
        store.add(authModel, auth)
        resolve('User created')
      }
    })
  }

This is the store.add function.

async function add (collection: any, data: any) {
  return await collection.create(data)
}

Note this code is writhed with Typescript.

Diesan Romero
  • 1,292
  • 4
  • 20
  • 45
  • I don't understand what your problem is, but you are not waiting for the two calls to `store.add()` to finish before resolving your promise. – jfriend00 Apr 10 '21 at 04:06

1 Answers1

1

You're missing the reference key when creating the Auth instance. The "foreign key" in MongoDB is the id of a document that has type Schema.Types.ObjectId and can be accessed with document._id.

So your code should look like:

const auth = { salt, hash };

const user = store.add(userModel, user);
auth.email = user._id;

store.add(authModel, auth);

Be aware that your store.add() function is an async function and you should wait for it's result like @jfriend00 said in the comments.

You can achieve that by making add() also an async funtion and doing:

const auth = { salt, hash };

const user = await store.add(userModel, user);
auth.email = user._id;

await store.add(authModel, auth);

or using the Promise approach by chaining .then(). You can read more about it here.

Drakmord2
  • 864
  • 6
  • 13
  • Thank you for your answer. That's solve my problem as well. Now when I delete my user it will keep its auth reference, is there a way to deal with this? I want their authentication removed as well. What I mean is, is there a method that can do it automatically or do I have to create it? – Diesan Romero Apr 10 '21 at 16:52
  • It can be achieved through Middlewares. [Here](https://stackoverflow.com/a/14349259) is a solution to implement this "cascade" delete. – Drakmord2 Apr 10 '21 at 18:20
  • I have understanding .remove is deprecated. It's recommendable to use it? – Diesan Romero Apr 10 '21 at 18:23
  • I'm not aware of that. It is still available in the [official documentation](https://mongoosejs.com/docs/middleware.html). Maybe a `document.remove()` is deprecated, but the middleware makes use of `model.remove()`. – Drakmord2 Apr 10 '21 at 18:33
  • Thanks. I already tried with that, and the .exec method. But the middleware is not running. I place another question in here https://stackoverflow.com/questions/67037269/trying-to-delete-a-object-reference-in-mongodb-with-mongoose-on-nodejs/67037585?noredirect=1#comment118495780_67037585 – Diesan Romero Apr 10 '21 at 18:40