-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unexpected behavior using different kinds of select #14115
Comments
In MongoDB projection, both are valid and behave the same: But in Mongoose projection it behaves differently. It is a bug. |
Please specify the mongoose version, unable to reproduce on 6.11.4 const mongoose = require('mongoose');
const testSchema = new mongoose.Schema({
liveMode: Number,
payment: {
clientPaymentMethod: String,
id: String
},
donation: {
frequency: Number,
amount: Number,
isMobile: Boolean
}
});
const Test = mongoose.model('Test', testSchema);
async function run() {
console.log('mongoose version', mongoose.version);
await mongoose.connect('mongodb://localhost:27017');
await mongoose.connection.dropDatabase();
await Test.create({
liveMode: 99,
payment: {
clientPaymentMethod: 'a payment method',
id: ''
},
donation: {
frequency: 5,
amount: 20,
isMobile: false
}
});
const selectFields = {
_id: 1,
livemode: 1,
'payment': {
clientPaymentMethod: 1
},
'donation': {
frequency: 1
},
};
const v2SelectFields = {
_id: 1,
livemode: 1,
'payment.clientPaymentMethod': 1,
'donation.frequency': 1,
};
const v1 = await Test.findOne().select(selectFields);
console.log('what is v1', v1);
console.log('====================================================');
const v2 = await Test.findOne().select(v2SelectFields)
console.log('what is v2', v2);
}
run(); |
The problem emerges when you have some default values, I was also looking at this issue and added two tests that fail to it('sets defaults on subdocs with subdoc projection (gh-14115)', async function() {
const userSchema = new mongoose.Schema({
name: String,
account: {
amount: Number,
owner: { type: String, default: 'OWNER' },
IBAN: String,
BIC: String,
churchTax: Number,
taxIds: [
{
/**
* This is a sub document, we do not want it to have a `_id`
*/
_id: false,
type: Schema.Types.Mixed,
country: {
type: String,
required: true
},
taxId: { type: String, required: true }
}
]
}
});
const User = db.model('User', userSchema);
await User.insertMany([{ name: 'user', account: { amount: 100, owner: 'John Doe', taxIds: [{ country: 'DE', taxId: '123456789' }] } }]);
const nestedProjectionDocFormat1 = await User.findOne({ name: 'user' }, { name: 1, address: { street: 1 } });
const nestedProjectionDocFormat2 = await User.findOne({ name: 'user' }, { name: 1, 'address.street': 1 });
// only address should be in the address subdoc
assert.strictEqual(nestedProjectionDocFormat1.account.amount, 100);
assert.strictEqual(nestedProjectionDocFormat2.account.amount, 100);
// both should not have other members
assert.strictEqual(nestedProjectionDocFormat1.account.owner, undefined);
assert.strictEqual(nestedProjectionDocFormat2.account.owner, undefined);
assert.strictEqual(nestedProjectionDocFormat1.account.taxIds, undefined);
assert.strictEqual(nestedProjectionDocFormat2.account.taxIds, undefined);
});
it('sets defaults on subdocs with subdoc selection (gh-14115)', async function() {
const userSchema = new mongoose.Schema({
name: String,
account: {
amount: Number,
owner: { type: String, default: 'OWNER' },
IBAN: String,
BIC: String,
churchTax: Number,
taxIds: [
{
/**
* This is a sub document, we do not want it to have a `_id`
*/
_id: false,
type: Schema.Types.Mixed,
country: {
type: String,
required: true
},
taxId: { type: String, required: true }
}
]
}
});
const User = db.model('User', userSchema);
await User.insertMany([{ name: 'user', account: { amount: 100, owner: 'John Doe', taxIds: [{ country: 'DE', taxId: '123456789' }] } }]);
const nestedProjectionDocFormat1 = await User.findOne({ name: 'user' }).select({ name: 1, account: { amount: 1 } });
const nestedProjectionDocFormat2 = await User.findOne({ name: 'user' }).select({ name: 1, 'account.amount': 1 });
console.log(nestedProjectionDocFormat1, nestedProjectionDocFormat2);
// only address should be in the address subdoc
assert.strictEqual(nestedProjectionDocFormat1.account.amount, 100);
assert.strictEqual(nestedProjectionDocFormat2.account.amount, 100);
// both should not have other members
assert.strictEqual(nestedProjectionDocFormat1.account.owner, undefined);
assert.strictEqual(nestedProjectionDocFormat2.account.owner, undefined);
assert.strictEqual(nestedProjectionDocFormat1.account.taxIds, undefined);
assert.strictEqual(nestedProjectionDocFormat2.account.taxIds, undefined);
}); |
This issue might be related to this one: |
There's no address property on your schema. You also don't create it in the insert many. I'm assuming that's a typo and you meant const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: String,
account: {
amount: Number,
owner: { type: String, default: 'OWNER' },
IBAN: String,
BIC: String,
churchTax: Number,
taxIds: [
{
/**
* This is a sub document, we do not want it to have a `_id`
*/
_id: false,
type: mongoose.Schema.Types.Mixed,
country: {
type: String,
required: true
},
taxId: { type: String, required: true }
}
]
}
});
const User = mongoose.model('User', userSchema);
async function run() {
await mongoose.connect('mongodb://localhost:27017');
await mongoose.connection.dropDatabase();
await User.insertMany([{ name: 'user', account: { amount: 100, owner: 'John Doe', taxIds: [{ country: 'DE', taxId: '123456789' }] } }]);
const nestedProjectionDocFormat1 = await User.findOne({ name: 'user' }, { name: 1, account: { amount: 1 } });
const nestedProjectionDocFormat2 = await User.findOne({ name: 'user' }, { name: 1, 'account.amount': 1 });
console.log(nestedProjectionDocFormat1.account.amount);
console.log(nestedProjectionDocFormat2.account.amount);
console.log(nestedProjectionDocFormat1.account.owner);
console.log(nestedProjectionDocFormat2.account.owner);
console.log(nestedProjectionDocFormat1.account.taxIds);
console.log(nestedProjectionDocFormat2.account.taxIds);
}
run() |
Bug is also present on mongoose 8 |
Prerequisites
Mongoose version
6.x.x
Node.js version
20.9.0
MongoDB version
5.10.19
Hey guys
I have an issue with using different kinds of
.select()
queryFirst case. The code below returns the expected behavior
Second case. If I use another kind of selection we could see different behaviour
I am not sure that the second case is valid for use, but it works. There are no rules for selecting nested fields in docs(maybe I missed)
I expected that the second case would work like the first case. Is it valid behavior?
The text was updated successfully, but these errors were encountered: