Mongoose: Los modelos base no respetan la selección: falso para discriminadores

Creado en 16 feb. 2017  ·  3Comentarios  ·  Fuente: Automattic/mongoose

¿Quieres solicitar una función o informar de un error ?
Insecto

¿Cuál es el comportamiento actual?
Cuando se utiliza un modelo base para recuperar un documento de modelo discriminador, no respeta select: false .

Si el comportamiento actual es un error, proporcione los pasos para reproducirlo.

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const co = require('co');
const chalk = require('chalk');

const GITHUB_ISSUE = `test-constructor-emit-bug`;

exec()
  .then(() => {
    console.log(chalk.green(`Successfully ran program`));
    process.exit(0);
  })
  .catch(error => {
    console.log(chalk.red(`Error: ${ error }\n${ error.stack }`));
    process.exit(2);
  });

function exec() {
  return co(function* () {
    const db = mongoose.createConnection(`mongodb://localhost:27017/${ GITHUB_ISSUE }`);
    const { Base, Discriminator } = createModels(db);
    const { baseDoc, discrimDoc } = yield seedDb({ Base, Discriminator });

    const docFromDb = yield Base.findById(discrimDoc._id) // does not honor select: false
    // const docFromDb = yield Discriminator.findById(discrimDoc._id); // honors select: false
    console.log(docFromDb.internal); // should not log `internal.password`
  });
}

function seedDb(models) {
  return co(function*() {
    const { Base, Discriminator } = models;

    yield [Base.remove({}), Discriminator.remove({})];

    const baseDoc = yield Base.create({ internal: { diseases: ['Malaria'] }});
    const discrimDoc = yield Discriminator.create({ internal: {
      diseases: ['MS'],
      password: 'plain_test_password_ftw'
    }});

    return { baseDoc, discrimDoc };
  });
}

function createModels(db) {
  const baseSchema = new mongoose.Schema({
    internal: {
      diseases: [{ type: String }]
    }
  });

  const Base = db.model('Base', baseSchema);
  const discriminatorSchema = new mongoose.Schema({
    internal: {
      password: { type: String, select: false }
    }
  });
  const Discriminator = Base.discriminator('Discriminator', discriminatorSchema);

  return { Base, Discriminator };
}

¿Cuál es el comportamiento esperado?
Probablemente deberíamos deseleccionar esos campos manualmente después de obtenerlos de la base de datos, ya que mangosta no sabe de antemano qué discriminadores seleccionar.

Mencione su versión de node.js, mongoose y MongoDB.
nodo 6.9.2, mangosta 4.8.3, mongodb 3.4

confirmed-bug

Todos 3 comentarios

Parece que estoy experimentando efectos secundarios inesperados por este cambio:

Tengo un modelo base A , con un modelo discriminador B .
Cuando consulto A por documentos usando una proyección de matriz $slice , los documentos resultantes del tipo A devuelven todas las propiedades (excluyendo las marcadas como select: false ), mientras que los documentos resultantes del tipo B solo devuelven propiedades _explícitamente_ marcadas como select: true o aquellas con un conjunto default . Aquellos con un conjunto default devuelven el valor predeterminado, no el valor realmente almacenado en la base de datos. Si no hay propiedades marcadas con select: true , solo se devuelven las propiedades con valores default (nuevamente con el valor predeterminado, no el valor de la tienda).

EDITAR : Ignore mi comentario, el problema era que la mangosta agrega la clave discriminadora a la consulta debajo del capó. La solución fue usar la función slice en la consulta.

Podría haber hablado demasiado pronto. Al probar tanto con la versión 4.13.4 como con la última master commit, veo el mismo comportamiento cuando solo uso la proyección slice .

Tomé el ejemplo original en este número y lo modifiqué para reproducir el comportamiento:

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const co = require('co');
const chalk = require('chalk');
mongoose.set('debug', true);
const GITHUB_ISSUE = `default-values-on-discriminator-documents`;

exec()
    .then(() => {
        console.log(chalk.green(`Successfully ran program`));
        process.exit(0);
    })
    .catch(error => {
        console.log(chalk.red(`Error: ${error}\n${error.stack}`));
        process.exit(2);
    });

function exec() {
    return co(function* () {
        const db = mongoose.createConnection(`mongodb://localhost:27017/${GITHUB_ISSUE}`);
        const { Base, Discriminator } = createModels(db);
        const { baseDoc, discrimDoc } = yield seedDb({ Base, Discriminator });

        const baseDocsFromDbWithSlice = yield Base.find().slice('array', 1)
        const baseDocsFromDb = yield Base.find()
        console.log(baseDocsFromDbWithSlice); // Discriminator document returns default value for propA (and not propB), base document returns stored value - unexpected
        console.log(baseDocsFromDb); // Discriminator and base document returns stored value for propA - expected
    });
}

function seedDb(models) {
    return co(function* () {
        const { Base, Discriminator } = models;

        yield [Base.remove({}), Discriminator.remove({})];

        const baseDoc = yield Base.create({
            propA: 'Hi',
            array: ["a", "b"]
        });
        const discrimDoc = yield Discriminator.create({
            propA: 'Hi',
            propB: 'Hello',
            array: ["a", "b"]
        });

        return { baseDoc, discrimDoc };
    });
}

function createModels(db) {
    const baseSchema = new mongoose.Schema({
        propA: { type: String, default: 'default value' },
        array: [{type: String}],
    });

    const Base = db.model('Base', baseSchema);
    const discriminatorSchema = new mongoose.Schema({
        propB: { type: String}
    });
    const Discriminator = Base.discriminator('Discriminator', discriminatorSchema);

    return { Base, Discriminator };
}

Este comportamiento cambió en 4.11.13 , por lo que sospeché que la causa era la resolución de este problema. Si no es así, estaré encantado de crear un nuevo problema.

Gracias por informar a @bruun , investigaremos lo antes posible: +1:

¿Fue útil esta página
0 / 5 - 0 calificaciones