Mongoose - Queries with OR and AND

0

I'm trying to make a query in mongoose and I can not think of how to put it together. In SQL it would be something like this:

SELECT * FROM MATERIAS 
WHERE
     activo = true AND 
     nivel = $nivel_id AND
    (alldisc = true OR disciplina = $disciplina_id)

where $nivel_id and $disciplina_id variables.

This same thing I'm writing in nodejs and mongoose and I can not think of a good way to do it.

What I have done so far is:

function getMateriasFilter(req, res) {
    var query = Materia.find({'active': true});

    if (req.query.nivel)        query.where('nivel', req.query.nivel);
    if (req.query.disciplina)   query.where('disciplina', req.query.disciplina).or('alldisc', true);

    query
        .populate('nivel')
        .populate('periodo')
        .populate('disciplina')
        .exec(function(err, result) {
            if (err) res.send(err);
            res.json(result); 
        });
}

The line with the discipline ifif complicates me. That condition would be that if the discipline filter exists, I have to bring the one that matches the discipline or those that have the alldisc field in true.

Thank you very much already.

    
asked by Ezequiel Cohort 21.02.2017 в 06:41
source

1 answer

0

I recommend always work in layers , delegate specific functionalities to each one so that you have a single responsibility. Remember that a highly coupled / cohesive application means a very low probability that you can scale and maintain in the future.

The next class acts as repository for a collection. Its function is simply to consult the database.

  

Tip: preferably tends to use Promesas instead of callbacks because it provides clean syntax in complex processes (avoiding the callback hell ) and In addition, you will benefit if you decide to use the recently approved specification async/await that will appear in ES2017 .

class MateriaRepository {
  filter (nivel disciplina) {
    let where = { active: true };

    if (nivel) {
      where.nivel = nivel;
    }

    if (disciplina) {
      where.$or = [
        {
          alldisc: true
        },
        {
          disciplina
        }
      ]
    }

    return (
      Materia
        .find(where)
        .populate('nivel')
        .populate('periodo')
        .populate('disciplina')
        .exec()
    );
  }
}

This way you can use these methods anywhere.

function getMateriasFilter (req, res) {
  let repository = new MateriaRepository();
  let { nivel, disciplina } = req.query;

  repository
    .filter(nivel, disciplina)
    .then((materias) => (
      res.jsonp(materias)
    ));
}

The previous query is explained as follows:

  • By default, where only specifies that only active subjects are selected ( active: true ).
  • If the nivel parameter is available, add an entry to where so that only active subjects are selected and have the specified level.
  • If the discipline parameter is available, an entry of type $or is added to where to select active , of a certain level and of a certain discipline or if the subject has alldisc: true .
  • answered by 21.02.2017 / 16:14
    source