Mongoose: Π‘Π°Π·ΠΎΠ²Ρ‹Π΅ ΠΌΠΎΠ΄Π΅Π»ΠΈ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ select: false для дискриминаторов

Π‘ΠΎΠ·Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π° 16 Ρ„Π΅Π²Ρ€. 2017  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ  Β·  Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: Automattic/mongoose

Π’Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ Π·Π°ΠΏΡ€ΠΎΡΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈΠ»ΠΈ ΡΠΎΠΎΠ±Ρ‰ΠΈΡ‚ΡŒ ΠΎΠ± ошибкС ?
Ошибка

Каково Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅?
Когда базовая модСль ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для получСния Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π° ΠΌΠΎΠ΄Π΅Π»ΠΈ дискриминатора, ΠΎΠ½Π° Π½Π΅ ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ select: false .

Если Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ являСтся ошибкой, ΡƒΠΊΠ°ΠΆΠΈΡ‚Π΅ шаги для воспроизвСдСния.

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

КакоС оТидаСмоС повСдСниС?
ВСроятно, Π½Π°ΠΌ слСдуСт ΠΎΡ‚ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π²Ρ‹Π±ΠΎΡ€ этих ΠΏΠΎΠ»Π΅ΠΉ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ послС извлСчСния ΠΈΠ· Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ…, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ мангуст Π·Π°Ρ€Π°Π½Π΅Π΅ Π½Π΅ Π·Π½Π°Π΅Ρ‚, ΠΊΠ°ΠΊΠΈΠ΅ дискриминаторы Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ.

ΠŸΠΎΠΆΠ°Π»ΡƒΠΉΡΡ‚Π°, ΡƒΠΊΠ°ΠΆΠΈΡ‚Π΅ свою Π²Π΅Ρ€ΡΠΈΡŽ node.js, mongoose ΠΈ MongoDB.
ΡƒΠ·Π΅Π» 6.9.2, мангуст 4.8.3, ΠΌΠΎΠ½Π³ΠΎΠ΄Π± 3.4

ВсС 3 ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

Π―, каТСтся, ΠΈΡΠΏΡ‹Ρ‚Ρ‹Π²Π°ΡŽ Π½Π΅ΠΎΠΆΠΈΠ΄Π°Π½Π½Ρ‹Π΅ ΠΏΠΎΠ±ΠΎΡ‡Π½Ρ‹Π΅ эффСкты ΠΎΡ‚ этого измСнСния:

Π£ мСня Π΅ΡΡ‚ΡŒ базовая модСль A с модСлью дискриминатора B .
Когда я Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°ΡŽ Ρƒ A Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹ с использованиСм ΠΏΡ€ΠΎΠ΅ΠΊΡ†ΠΈΠΈ массива $slice , Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹ Ρ‚ΠΈΠΏΠ° A Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ всС свойства (Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ Ρ‚Π΅Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Ρ‹ ΠΊΠ°ΠΊ select: false ), Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹ Ρ‚ΠΈΠΏΠ° B Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ свойства, _явно_ ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Π½Ρ‹Π΅ ΠΊΠ°ΠΊ select: true ΠΈΠ»ΠΈ Ρ‚Π΅, для ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π·Π°Π΄Π°Π½ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ default . Π’Π΅, Ρƒ ΠΊΠΎΠ³ΠΎ Π΅ΡΡ‚ΡŒ default set, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, Π° Π½Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, фактичСски хранящССся Π² Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ…. Если Π½ΠΈΠΊΠ°ΠΊΠΈΠ΅ свойства Π½Π΅ ΠΎΡ‚ΠΌΠ΅Ρ‡Π΅Π½Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ select: true , Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ свойства со значСниями default (ΠΎΠΏΡΡ‚ΡŒ ΠΆΠ΅ со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, Π° Π½Π΅ со Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π°).

Π Π•Π”ΠΠšΠ’Π˜Π ΠžΠ’ΠΠ’Π¬ : Π½Π΅ ΠΎΠ±Ρ€Π°Ρ‰Π°ΠΉΡ‚Π΅ внимания Π½Π° ΠΌΠΎΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ, ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π»Π°ΡΡŒ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ мангуст добавляСт ΠΊΠ»ΡŽΡ‡ дискриминатора ΠΊ запросу ΠΏΠΎΠ΄ ΠΊΠ°ΠΏΠΎΡ‚ΠΎΠΌ. РСшСниСм Π±Ρ‹Π»ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ slice Π² запросС.

Π― ΠΌΠΎΠ³ Π·Π°Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ΡŒ слишком Ρ€Π°Π½ΠΎ. ВСстируя ΠΊΠ°ΠΊ Π²Π΅Ρ€ΡΠΈΡŽ 4.13.4, Ρ‚Π°ΠΊ ΠΈ послСднюю master commit, я наблюдаю Ρ‚Π°ΠΊΠΎΠ΅ ΠΆΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΈ использовании Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΎΠ΅ΠΊΡ†ΠΈΠΈ slice .

Π― взял исходный ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΈΠ· этого выпуска ΠΈ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ» Π΅Π³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ воспроизвСсти ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅:

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

Π­Ρ‚ΠΎ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ измСнилось Π² 4.11.13 , поэтому я ΠΏΠΎΠ΄ΠΎΠ·Ρ€Π΅Π²Π°Π», Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΡ‡ΠΈΠ½ΠΎΠΉ являСтся Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ этой ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹. Если Π½Π΅Ρ‚, я с Ρ€Π°Π΄ΠΎΡΡ‚ΡŒΡŽ создам Π½ΠΎΠ²Ρ‹ΠΉ выпуск

Бпасибо Π·Π° сообщСниС @bruun , расслСдуСм ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ скорСС: +1:

Π‘Ρ‹Π»Π° Π»ΠΈ эта страница ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ?
0 / 5 - 0 Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³ΠΈ

Π‘ΠΌΠ΅ΠΆΠ½Ρ‹Π΅ вопросы

Soviut picture Soviut  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ

ghost picture ghost  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ

efkan picture efkan  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ

lukasz-zak picture lukasz-zak  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ

wlingke picture wlingke  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ