e-oj / Fawn

Transactions for MongoDB (See the README)
https://www.npmjs.com/package/fawn
MIT License
486 stars 54 forks source link

References id #16

Closed yamila-fraiman closed 7 years ago

yamila-fraiman commented 7 years ago

Hi, I'm trying to create a document with references and when I call save, the field is saved as a String instead of ObjectId.

let mySchema = Schema({
    user: { type: Schema.Types.ObjectId, ref: 'User', required: true, index: true },
    comment: { type: String, required: true }
});

and the result is:

{
    "_id" : ObjectId("599984be9a86b02f9c3f256e"),
    "user" : "5997a409df4cc84e8ca3a8de",
    "comment": "testing"
}

I tried inserting comments using user.id and user._id.

e-oj commented 7 years ago

Let me see the code you're trying to use

yamila-fraiman commented 7 years ago
let comment = {
    user: req.user._id, //Also tried req.user and req.user.id
    comment: 'testing'
};
let transaction = Fawn.Task();
transaction.save('comments', comment);
...
transaction.run({useMongoose: true})
e-oj commented 7 years ago

Try casting the _id to an ObjectId before saving.

let comment = {
    user: mongoose.Types.ObjectId(req.user._id), // cast to ObjectId
    comment: 'testing'
};

let transaction = Fawn.Task();
transaction.save('comments', comment);
...
transaction.run({useMongoose: true})
yamila-fraiman commented 7 years ago

Have you tried it? It's not working for me. Also I think that cast should be done if I use user.id instead of user._id that is already an object id.

e-oj commented 7 years ago

Yeah it works for me. I haven't been able to reproduce this.

let mongoose = require("mongoose");
let Schema = mongoose.Schema;
let Fawn = require("fawn");

mongoose.connect("mongodb://127.0.0.1:27017/AnimalDB", {useMongoClient: true});
Fawn.init(mongoose, "_tasks_");

let Animals = mongoose.model("Animals", new Schema({
  name: String
  , kid: {type: Schema.Types.ObjectId, ref: 'Animals'}
  , color: String
  , bipedal: Boolean
}));

let animal1 = new Animals({
  name: "Bob"
  , color: "magenta"
  , bipedal: true
});

let animal2 = {
  name: "Giraffe"
  , color: "yellow"
  , bipedal: false
  , kid: animal1._id // animal1._id.toString() also works
};

async function test() {
  let result = await Fawn.Task()
    .save(animal1)
    .save("Animals", animal2)
    .run({useMongoose: true});

  console.log(result);
}

test();

results in

{
    "_id" : ObjectId("5999b9f2e8704f074fe96e3c"),
    "name" : "Bob",
    "color" : "magenta",
    "bipedal" : true,
    "__v" : 0
}
{
    "_id" : ObjectId("5999b9f2e8704f074fe96e3d"),
    "name" : "Giraffe",
    "color" : "yellow",
    "bipedal" : false,
    "kid" : ObjectId("5999b9f2e8704f074fe96e3c"),
    "__v" : 0
}
e-oj commented 7 years ago

Did you initialize Fawn with mongoose? Because I could only reproduce by leaving out this line

Fawn.init(mongoose, "_tasks_");

If you're using mongoose, you need to initialize with your mongoose instance

yamila-fraiman commented 7 years ago

I'm calling init when I start the server: Fawn.init(mongoose). Also I checked the source code and I think it doesn't matter if I pass an object or a string because it calls xcode where you stringify the id. However, if I call comment.save() without using transactions and with string ids, it works so I don't understand why with fawn I'm getting strings in my database and It is not calling pre save.

e-oj commented 7 years ago

Are there any major differences between your code and how I've tried to reproduce this issue? I need to recreate the error to fix it.

yamila-fraiman commented 7 years ago

My fault! I write the model name in plural and lowercase (mongo name) instead of mongoose name. Sorry and thank you sooo much!

e-oj commented 7 years ago

No problem :+1: