Problems creating or updating records from array

2

I need help. I am setting up a system for loading notes per subject per student.

I put together a spreadsheet to load these notes (angular) and once they finished loading, I sent all that object to be processed, but when I try to save those notes (I search the base, if there is a modification, if not, I believe it) , it generates all the equal records.

The code is this:

var query = {};

query.delegacion = data.delegacion;
query.disciplina = data.disciplina;
query.periodo    = data.periodo;
query.nivel      = data.nivel;
query.anio       = data.anio;


for (var alumno in data.notas) {
    var id_alumno = alumno;
    for (var materia in data.notas[alumno]) {
        var id_materia = materia;
        var nro_nota   = data.notas[alumno][materia];

        query.alumno = id_alumno;
        query.materia = id_materia;

        Nota.find(query)
        .exec(function(err, result) {
            if (err) res.send(err);
            if (result.data) {
                result.nota = nro_nota;
                result.save(function(err, doc) { });
            } else {
                var notas = new Nota();
                notas.delegacion = data.delegacion;
                notas.disciplina = data.disciplina;
                notas.periodo  = data.periodo;
                notas.nivel    = data.nivel;
                notas.anio     = data.anio;
                notas.alumno   = id_alumno;
                notas.materia  = id_materia;
                notas.fecha    = req.body.fecha;
                notas.nota     = nro_nota;
                notas.recupera = false;

                notas.save(function(err, doc) { });
            }
        });
    }
}

This is the object I receive in NodeJS:

{ 
    delegacion: '57e3108ee0a5427810ed1dd1',
    disciplina: '589888d6dfae11da7c38c22e',
    periodo: '58a67d7798f945ea6928b055',
    nivel: '58a67278038397c566181428',
    anio: 2017,
    notas: { 
        '584878b97d60ab072930fba9': { 
            '58ae61d38f89a5574c28bdd4': 8.5 
        },
        '57e4393fcc6f162d3166925e': { 
            '58a71819fc82f69b0e1cf70b': 10,
            '58ae61d38f89a5574c28bdd4': 7.5 
        } 
    } 
}

I understand that it can be handled with promises, but I did not realize very well how to implement them.

Of course, I thank you for any help you can give me.

    
asked by Ezequiel Cohort 01.03.2017 в 16:36
source

2 answers

1

When you pass the query variable to do the find in Note, you only have to pass the student_id and the_id_id, because as you have declared, you are waiting to find the document with all the parameters:

query.delegacion = data.delegacion;
query.disciplina = data.disciplina;
query.periodo    = data.periodo;
query.nivel      = data.nivel;
query.anio       = data.anio;

I also suggest you pass to a function the part of creating Note, you pass the parameters of the query only student_id and master_id, nro_note and use a callback:

function agregarNota(query, nro_nota, callback) {
        Nota.find(query)
            .exec(function(err, result) {
                if (err) res.send(err);
                if (result.data) {
                    result.nota = nro_nota;
                    result.save(function(err, doc) { });
                    return callback(true)
                } else {
                    var notas = new Nota();
                    notas.delegacion = data.delegacion;
                    notas.disciplina = data.disciplina;
                    notas.periodo  = data.periodo;
                    notas.nivel    = data.nivel;
                    notas.anio     = data.anio;
                    notas.alumno   = id_alumno;
                    notas.materia  = id_materia;
                    notas.fecha    = req.body.fecha;
                    notas.nota     = nro_nota;
                    notas.recupera = false;

                    notas.save(function(err, doc) { });
                    return callback(true);
                }
            });
    }

I think the problem is in the query variable, so you pass your query to mongodb:

{ delegacion: 'delegacion',
  disciplina: 'disc',
  periodo: 'periodo',
  nivel: 1,
  anio: 2017,
  alumno: '57e4393fcc6f162d3166925e',
  materia: '58ae61d38f89a5574c28bdd4' }

If you prefer to leave the search function inside the for loop, the variable nro_nota can change, take it into account.

    
answered by 01.03.2017 / 23:32
source
1

Use ES6 code as much as you can so you can take advantage of the many novelties offered by the most modern version of the language. First, never use var as a control variable if you are going to reference it in a callback simply because it will not work as you think.

JavaScript is an asynchronous language, callbacks are not executed sequentially in the code, if not in parallel, making it quite possible that when the callback is executed the loop has already ended and always references the last record each time. You can read about closures to have a more detailed idea about it.

Another tip is that always modularize your code , always, no matter how small. Identify responsibilities, delégate them, divide your application into layers , each with a single responsibility. For example, all logic with database should be isolated from the rest and serve only as a service for when you need to bring data from the database.

Your code, it looks like this using ES6:

Router handler

let notasRepository = new NotasRepository();

for (let alumno in data.notas) {
  for (let materia in data.notas[alumno]) {
    let nota = data.notas[alumno][materia];

    notasRepository.createOrUpdate({
      delegacion: data.delegacion,
      disciplina: data.disciplina,
      periodo: data.periodo,
      nivel: data.nivel,
      anio: data.anio,
      fecha: req.body.fecha,
      materia,
      alumno,
      nota
    })
    .then(doc => {
      // tienes disponible cada documento creado o actualizado
    });
  }
}

NotasRepository

export default class NotasRepository {

  updateOrCreate (params) {
    let where = (
      ({ delegacion, disciplina, periodo, nivel, anio, alumno, materia })) =>
      ({ delegacion, disciplina, periodo, nivel, anio, alumno, materia })
    )(params);

    return new Promise((resolve) => {
      Nota
        .find(query)
        .then(doc => {
          if (doc) {
            doc.nota = params.nota;
            doc.save().then(() => {
              resolve(doc);
            });
          } else {
            where.materia = params.materia;
            where.alumno = params.alumno;
            where.fecha = params.fecha;
            where.nota = params.nota;
            where.recupera = false;

            Nota.create(where).then((doc) => {
              resolve(doc);
            });
          }
        });
    });
  }
}
    
answered by 02.03.2017 в 01:39