Mongoose: Modelos de base não honram a seleção: falso para discriminadores

Criado em 16 fev. 2017  ·  3Comentários  ·  Fonte: Automattic/mongoose

Você quer solicitar um recurso ou relatar um bug ?
Erro

Qual é o comportamento atual?
Quando um modelo básico é usado para recuperar um documento de modelo discriminador, ele não honra select: false .

Se o comportamento atual for um bug, forneça as etapas para reproduzir.

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 };
}

Qual é o comportamento esperado?
Provavelmente deveríamos desmarcar esses campos manualmente após buscar no banco de dados, uma vez que o mongoose não sabe com antecedência quais discriminadores selecionar.

Mencione sua versão node.js, mongoose e MongoDB.
nó 6.9.2, mangusto 4.8.3, mongodb 3.4

confirmed-bug

Todos 3 comentários

Parece que estou experimentando efeitos colaterais inesperados com essa mudança:

Eu tenho um modelo básico A , com um modelo discriminador B .
Quando eu consulto A para documentos usando uma projeção de array $slice , os documentos resultantes do tipo A retornam todas as propriedades (exceto aquelas marcadas como select: false ), enquanto os documentos resultantes são do tipo B retorna apenas propriedades _explicitamente_ marcadas como select: true ou aquelas com um conjunto default . Aqueles com um conjunto default retornam o valor padrão, não o valor realmente armazenado no banco de dados. Se nenhuma propriedade estiver marcada com select: true , apenas as propriedades com valores default serão retornadas (novamente com o valor padrão, não o valor da loja).

EDIT : Desconsidere meu comentário, o problema era que o mangusto adiciona a chave discriminadora à consulta nos bastidores. A solução foi usar a função slice na Consulta.

Eu posso ter falado muito cedo. Testando com a versão 4.13.4 e o master commit mais recente, estou vendo o mesmo comportamento ao usar apenas a projeção slice .

Peguei o exemplo original neste problema e modifiquei para reproduzir o comportamento:

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 };
}

Esse comportamento mudou em 4.11.13 , e é por isso que suspeito que a causa seja a resolução para esse problema. Caso contrário, ficarei feliz em criar um novo problema

Obrigado por relatar @bruun , investigarei o mais

Esta página foi útil?
0 / 5 - 0 avaliações