5

I need to save some sub documents in a schema which is sub document of a schema. The save function is this:

exports.add = function(req, res){
var cliente = new Cliente(req.body);
var sedi = [];

for(var key in req.body.sede){
    var sede = new Sede(req.body.sede[key]);

    var luoghi_consegna_sedi = [];

    for(jey in req.body.sede[key].lcs){
        var luogo_consegna_sede = new LuoghiConsegnaSede(req.body.sede[key].lcs[jey]);

        //Sub document
        luoghi_consegna_sedi.push(luogo_consegna_sede);
    }

    sede.luoghi_consegna_sedi = luoghi_consegna_sedi;

    //Sub docuemnt
    sedi.push(sede);
}

cliente.sedi = sedi;

cliente.save(function(err){
    if(err)
        return res.sendStatus(400);

    return res.json(cliente);
});
};

The problem is that the top parent schema (cliente) is saved on mongoldb, while the two types of sub documents don't. In cliente.sedi the array is filled with sede objectid, but on mongoldb the sede table doesn't exists (and the same for luoghi_consegna_sedi). If I manually save sede and luoghi_consegna_sedi before push them in their arrays, the two tables are creates and filled with data, but if I run populate() on cliente.sedi I get an empty array. The 3 Schemas are these: Cliente

var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var ClienteSchema = new Schema({
data_status: String,
status_cliente: Number,
titolo_cliente: String,
cognome: String,
nome: String,
ragione_sociale: String,
codice_fiscale: String,
partita_iva: String,
data_nascita: String,
luogo_nascita: String,
business: {
    type: Boolean,
    default: false
},
consumer: {
    type: Boolean,
    default: false
},
sedi: {
    type: [Schema.ObjectId],
    ref: 'Sede'
},
eliminato: {
    type: Boolean,
    default: false
},
created: {
    type: Date,
    default: Date.now
}
});

ClienteSchema.set('toJSON', {getters: true});

mongoose.model('Cliente', ClienteSchema);

Sede

var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var SedeSchema = new Schema({
denominazione_sede: String,
tipo_sede: String,
tipo_indirizzo: String,
indirizzo: String,
numero_civico: String,
citofonare: String,
interno: String,
piano: String,
scala: String,
citta: String,
provincia: String,
cap: String,
regione: String,
paese: String,
telefono_1: String,
telefono_2: String,
email: String,
agente_assegnato_1: {
    type: Schema.ObjectId,
    ref: 'User'
},
agente_assegnato_2: {
    type: Schema.ObjectId,
    ref: 'User'
},
agente_assegnato_3: {
    type: Schema.ObjectId,
    ref: 'User'
},
agente_assegnato_4: {
    type: Schema.ObjectId,
    ref: 'User'
},
agente_assegnato_5: {
    type: Schema.ObjectId,
    ref: 'User'
},
agente_assegnato_jolly: {
    type: Schema.ObjectId,
    ref: 'User'
},
titolo_rif: String,
cognome_rif: String,
nome_rif: String,
cellulare_rif: String,
email_rif: String,
telefono_rif: String,
luoghi_consegna_sedi:{
    type: [Schema.ObjectId],
    ref: 'LuoghiConsegnaSede'
},
eliminato: {
    type: Boolean,
    default: false
},
created: {
    type: Date,
    default: Date.now
}
});

SedeSchema.set('toJSON', {getters: true});

mongoose.model('Sede', SedeSchema);

Luoghi_consegna_sedi

var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var LuoghiConsegnaSedeSchema = new Schema({
titolo_rif: String,
cognome: String,
nome: String,
tipo_sede_consegna: String,
sede_consegna: String,
telefono_1: String,
telefono_2: String,
cellulare_rif: String,
email_rif: String,
telefono_rif: String,
tipo_indirizzo_consegna: String,
indirizzo_consegna: String,
n_civico_consegna: String,
piano_consegna: String,
interno_consegna: String,
scala_consegna: String,
citofonare_consegna: String,
citta_consegna: String,
provincia_consegna: String,
regione_consegna: String,
cap_consegna: String,
paese_consegna: String,
eliminato: {
    type: Boolean,
    default: false
},
created: {
    type: Date,
    default: Date.now
}
});

LuoghiConsegnaSedeSchema.set('toJSON', {getters: true});

mongoose.model('LuoghiConsegnaSede', LuoghiConsegnaSedeSchema);
pindol
  • 2,110
  • 6
  • 35
  • 52

1 Answers1

3

Your issues is saving refs to other documents.

cliente.sedi = [];

for(var key in req.body.sede){
    var sede = new Sede(req.body.sede[key]);

    var luoghi_consegna_sedi = [];

    for(jey in req.body.sede[key].lcs){
        var luogo_consegna_sede = new LuoghiConsegnaSede(req.body.sede[key].lcs[jey]);

        // save luogo_consegna_sede and then push its _id
        luogo_consegna_sede.save();
        luoghi_consegna_sedi.push(luogo_consegna_sede._id);
    }

    sede.luoghi_consegna_sedi = luoghi_consegna_sedi;

    // Save sede and then push its id
    sede.save();
    cliente.sedi.push(sede._id);
}

cliente.save(function(err){
    if(err)
        return res.sendStatus(400);

    return res.json(cliente);
});
Edward Lee
  • 951
  • 5
  • 14
  • cliente.sedi is [Schema.ObjectId]. If I do a console log of var cliente I see that cliente.sedi doesn't exists and also in sede there is no luoghi_consegna_sedi field, but instead there is lcs (take from req.body). Why i can't set luoghi_consegna_sedi and sedi fields? – pindol Apr 24 '15 at 15:56
  • My guess was wrong. Does sedi have its own Schema and cliente.sedi reference to the Schema? – Edward Lee Apr 24 '15 at 17:16
  • Yes exactly. sedi is an array of objectid with ref to sede (the schema name for sedi) – pindol Apr 24 '15 at 18:12
  • @pindol You have to call `cliente.markModified('sedi')` otherwise mongoose won't push the changes. see [this](http://mongoosejs.com/docs/faq.html), question 1. – Tony Apr 24 '15 at 19:24
  • @Tony Good point, mongoose doesn't create getters/setters for array indexes. However, @pindol tries to save new document, so `markModified` is not required in this case. – Edward Lee Apr 24 '15 at 19:33
  • @EdwardLee Granted I'm having trouble following due to the language difference, but OP mentions the issue isn't with saving the sub documents. The issue is that `cliente` isn't persisting the `sedi` array. I think this would require the `markModified`. – Tony Apr 24 '15 at 19:39
  • I don't see use of `markModified` in the [mongoose example of populate](http://mongoosejs.com/docs/populate.html) so maybe you're right. Or OP skipped a step. – Tony Apr 24 '15 at 19:44
  • @Tony Let's see what pindol gets. – Edward Lee Apr 24 '15 at 20:14
  • Thank you all for the replies. I edited the code with cliente.sedi = sedi; cliente.markModified('sedi'); but it doesn't work. It only creates cliente doc on mongodb and not sedi and luoghi_consegna_sedi – pindol Apr 25 '15 at 07:30
  • I missed `Luoghi_consegna_sedi` document. this document should be saved and then pass its id to `sedi` – Edward Lee Apr 27 '15 at 14:13
  • sede doesn't get saved anyway – pindol Apr 27 '15 at 15:07
  • What is in `sede.luoghi_consegna_sedi`? – Edward Lee Apr 27 '15 at 15:19
  • an array of LuoghiConsegnaSede. I updated the question, so you can see the 3 schemas – pindol Apr 27 '15 at 15:27
  • if I manually save sede and luogo_consegna_sede as you did in your answer, data is written on mongodb but when I run populate('sedi') i get an empty array – pindol Apr 27 '15 at 15:32
  • `sede.luoghi_consegna_sedi` should be array of luogo_consegna_sede id, not object itself. Please try with `luoghi_consegna_sedi.push(luogo_consegna_sede._id);` – Edward Lee Apr 27 '15 at 15:40