saving ref of another document with mongoose and nodejs

mongoose reference schema in another file
mongoose relationships
mongoose reference another schema
mongoose save multiple documents
mongoose populate match
mongoose populate after save
mongoose populate array
mongoose find by reference field

i am new using mongodb and i am practicing with ref and populate... but i have a silly problem.

i am receiving from my client a object like this.

    {
    "name": "Jhon"
    "books": [
              { 
                "title": "whatever",
                 "pages": 300
              },
              {
                "title": "otherBook",
                 "pages": 450
              }
             ]
    }

So i have two schemas, authorSchema and booksSchema... so what i pretend is save the books and take the _id of each book to save the author with it.

My code in nodejs

authorCtrl.saveAuthor = (req, res) => {

    var booksId= []

    for (i = 0; i < req.body.books.length; i++) {
        booksModel.create(req.body.books[i], function (err, book) {
            booksId.push(book._id)
        })
    }

    var author= {
        name: req.body.name,
        books: booksId
    }

    console.log(author) // here i check and books array is empty,

    authorModel.create(author).then((authorSaved) => {
        res.json(authorSaved)
    }).catch(err => {
        res.json(err)
    })
}

i know it is an asynchronous problem... but how can i do it??.. or what is the best practice to ref collections?

/////EDIT//////

Here are my schemas

Authors Schema

const mongoose = require('mongoose')
const { Schema } = mongoose;


const authorsSchema = new Schema({
    name: { type: String },
    books: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'books'
    }]
})


module.exports = mongoose.model('authors', authorsSchema);

Books Schema

const mongoose = require('mongoose')
const { Schema } = mongoose;


const booksSchema = new Schema({
    title: { type: String },
    pages: { type: Number }

})


module.exports = mongoose.model('books', booksSchema);

Authors Schema:

const mongoose = require('mongoose')
const { Schema } = mongoose;

const authorsSchema = new Schema({
    name:  String,
    books: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Book'
    }]
})

module.exports = mongoose.model('Author', authorsSchema);

Books Schema:

const mongoose = require('mongoose')
const { Schema } = mongoose;

const booksSchema = new Schema({
    title: String,
    pages: Number,
})

module.exports = mongoose.model('Book', booksSchema);

NodeJS Code:

const author = {
        name: req.body.name
    }

AuthorModel.create(author, (error, createdAuthor)=>{
  //handle error

        BookModel.insertMany(req.body.books, function (err, createdbooks) {
            // handle error
            createdAuthor.books.push(createdbooks); 
            createdAuthor.save();
        })   
}

Mongoose v5.9.26: Query Population, Saving refs. Saving refs to other documents works the same way you normally save properties, just� I'm using mongoose + socket.io as CRUD between client and server. As I'm using sockets, there is a private scope individual for each client's socket, in which, for future use without making db find calls, I would like to store a reference of mongoose document, that I once found for this user.

Try this,

authorCtrl.saveAuthor = (req, res) => {
var booksId= [];

for (var i = req.body.books.length - 1; i >= 0; i--) {
    booksModel.create(req.body.books[i], (err, book) => {
        booksId.push(book._id);
        if(i == 0) { // This if condition executes at the end of the for loop.
            var author= {
                name: req.body.name,
                books: booksId
            };

            console.log(author);

            authorModel.create(author).then((authorSaved) => {
                res.json(authorSaved);
            }).catch(err => {
                res.json(err);
            });
        }
    });
}

}

Hope it helps...

Mongoose: Saving ref of another document into an array of objects , Mongoose: Saving ref of another document into an array of objects document returns empty array - node.js. This means that Mongoose allows you to define objects with a strongly-typed schema that is mapped to a MongoDB document. Mongoose provides an incredible amount of functionality around creating and working with schemas. Mongoose currently contains eight SchemaTypes that a property is saved as when it is persisted to MongoDB. They are: String; Number

You can do it with Javascript promises as below:

            var booksId = [];
            var promises = [];
            req.body.books.forEach(element => {
                promises.push(insertBook(element));
            });
            Promise.all(promises)    
            .then(function(data){ 
                /* do stuff when success */
                console.log('##GREAT##',booksId);
                /*** INSERT ARRAY OF BOOK IDs INTO authorModel***/
            })
            .catch(function(err){ 
                /* error handling */ 
            });

            function insertBook(element){
                return new Promise(function(resolve, reject){
                    var book = new booksModel({
                        title: element.title,
                        page:  element.page  
                    });

                    book.save(function(err,data){
                        if(err){
                            console.log(err);
                            reject(err)
                        }else{
                            console.log('#success');
                            booksId.push(data._id)
                            resolve();
                        }
                    });
                });
            }

Mongoose Relationships Tutorial – Vegibit, Mongoose Validation Examples | Node.js MongoDB User Registration → We'll have a look at Reference Based Relationships (Normalization) as well as Embedded Documents The other approach to relationships is to embed a related document inside of another document. const result = await publisher. save();. Insert document to MongoDB - To insert single document to MongoDB, call save() method on document instance. Callback function(err, document) is an optional argument to save() method. Insertion happens asynchronously and operations dependent on the inserted document has to be taken care. Find Example script.

mongoose: Referencing schema in properties or arrays, When using a NoSQL database like MongoDb, most of the time you'll have approach and need to reference other documents by the ObjectIds. you how to deal with these references using Node.js and the mongoose ODM. Now lets save the Post and after it got created, query for all existing Posts. You should not have to create an instance of the Document class without going through a model. Retrieving. When you load documents from MongoDB using model functions like findOne(), you get a Mongoose document back. const doc = await MyModel.findOne(); doc instanceof MyModel; // true doc instanceof mongoose.Model; // true doc instanceof

Mongoose document references with a one-to-many relationship , Here is an example of Mongoose. I believe this is what you looking for: var mongoose = require('mongoose'). , Schema = mongoose.Schema. The refPath option is a more sophisticated alternative to ref. If ref is just a string, Mongoose will always query the same model to find the populated subdocs. With refPath, you can configure what model Mongoose uses for each document.

How Create Relationships with Mongoose and Node.js ( with real , Basically is saved the _id from one collection to another collection ( {type: mongoose.Schema.Types.ObjectId,ref:'NameOfSchema'} ).Where the� const Kitten = mongoose.model('Kitten', kittySchema); A model is a class with which we construct documents. In this case, each document will be a kitten with properties and behaviors as declared in our schema. Let's create a kitten document representing the little guy we just met on the sidewalk outside:

Comments
  • can you post your schemas too?
  • @ArootinAghazaryan posted, thank you for check it :)
  • it has sense... but is not working... i have this error (node:11848) UnhandledPromiseRejectionWarning: ParallelSaveError: Can't save() the same doc multiple times in parallel. Document: 5c6e2373c5a2a62e48f0deed
  • i checked the mongoshell and i have one author but just one book... and i sent two books from my client, but the books are added well
  • it's because it's not possible to save() a document multiple times. look at my edit. i took the save() out of the loop. it should work fine now.
  • it is not saving the books inside the AuthorSchema... i check the collection and the array is empty, but the book was added... damn this is getting me crazy
  • let me think :) this is an async problem. the save() is being called before the Book is created!