Comments (6)
I am also able to reproduce with Document.prototype.$clone
instead of Ramda's clone by modifying an existing unit-test to use a subdocument array:
it.only('modification of test "$clone() (gh-11849)"', async function() {
const schema = new mongoose.Schema({
subDocArray: [{
name: {
type: String,
validate: {
validator: (v) => v !== 'Invalid'
}
}
}]
});
const Test = db.model('Test', schema);
const item = await Test.create({ subDocArray: [{ name: 'Test' }] });
const doc = await Test.findById(item._id);
const clonedDoc = doc.$clone();
// This assertion fails
assert.deepEqual(clonedDoc.subDocArray[0], doc.subDocArray[0]);
});
from mongoose.
const mongoose = require('mongoose');
const assert = require('assert');
const testSchema = new mongoose.Schema({
subDocArray: [{
name: {
type: String,
validate: {
validator: (v) => v !== 'Invalid'
}
}
}]
});
const Test = mongoose.model('Test', testSchema);
async function run() {
await mongoose.connect('mongodb://localhost:27017');
await mongoose.connection.dropDatabase();
await Test.create({ subDocArray: [{ name: 'Test' }] });
const doc = await Test.findOne();
const cloneTrooper = doc.$clone();
assert.deepEqual(cloneTrooper.subDocArray[0], doc.subDocArray[0]);
console.log('done');
}
run();
from mongoose.
I repro-ed OP's post using the following:
const R = require('ramda');
const mongoose = require('mongoose');
const OrganizationModel = mongoose.model('Organization', mongoose.Schema({ members: [{ user: 'ObjectId' }] }));
const UserModel = mongoose.model('User', mongoose.Schema({ members: ['ObjectId'] }));
void async function main() {
await mongoose.connect('mongodb://127.0.0.1:27017/mongoose_test');
let foundOrgModel = await OrganizationModel.findOne({});
if (!foundOrgModel) {
// create user
const user = await UserModel.create({})
// create org
foundOrgModel = await OrganizationModel.create({ members: [{ user: user._id }] })
}
foundOrgModel = await OrganizationModel.findOne({})
const members = R.clone(foundOrgModel.members);
console.log(members[0]._id.toString()) // crashes
}();
@gitkrakel your issue looks unrelated to OP's, but we'll take a look at that as well
from mongoose.
@Axosoft-Ashley the R.clone()
issue comes down to the fact that, in Mongoose 5.x, the ObjectId class from the bson library stored its data in an id
property. In Mongoose 8.x, the ObjectId class from the bson library stores its data in a Symbol('kId')
property. And, internally, R.clone()
uses a for/in
loop to iterate the object to clone, which doesn't loop over symbols.
I'll do some more digging to see if there's a way we can reconcile these two. But given that R.clone()
isn't extensible, it looks like our only options are to either 1) update the bson library to make the raw data associated with an ObjectId stored in an own non-symbol property on the ObjectId instance, 2) update Ramda to clone symbols. For example, updating Ramda's _clone()
function to use the following seems to work:
for (var key of Object.keys(value).concat(Object.getOwnPropertySymbols(value))) {
if (Object.prototype.hasOwnProperty.call(value, key)) {
copiedValue[key] = deep ? _clone(value[key], true, map) : value[key];
}
}
from mongoose.
Actually, it looks like [email protected] (just released today) fixes this issue, so R.clone()
works fine now, following script outputs the ObjectId as a string if Mongoose installs [email protected]:
const R = require('ramda');
const mongoose = require('mongoose');
const OrganizationModel = mongoose.model('Organization', mongoose.Schema({ members: [{ user: 'ObjectId' }] }));
const UserModel = mongoose.model('User', mongoose.Schema({ members: ['ObjectId'] }));
void async function main() {
await mongoose.connect('mongodb://127.0.0.1:27017/mongoose_test');
let foundOrgModel = await OrganizationModel.findOne({});
if (!foundOrgModel) {
// create user
const user = await UserModel.create({})
// create org
foundOrgModel = await OrganizationModel.create({ members: [{ user: user._id }] })
}
foundOrgModel = await OrganizationModel.findOne({})
const members = R.clone(foundOrgModel.members);
console.log(members[0]._id.toString()) // crashes
}();
Related issue here: mongodb/js-bson#643. So @Axosoft-Ashley please re-run npm install
, and update your package-lock.json
to use [email protected] if you have a package-lock.json
.
from mongoose.
@vkarpov15 I tested in my playground and it did appear to fix the issue with 6.4.0 of bson! Thank you 😄
from mongoose.
Related Issues (20)
- $switch in $expr in filter query failed: Cannot read properties of undefined (reading 'map') HOT 2
- bulkWrite operations on any sharded collection are completely broken in 8.4.1+
- Mongoose is creating ghost/empty collections for every database under a project where multiple schemas are used HOT 5
- populate not working without lean() HOT 6
- Manually populated documents get saved as strings instead of `ObjectId`s in combination with SchemaType getter
- bulkSave doesn't throw an error even if one of the submitted documents was not updated HOT 7
- Can we include dataloader for .populate method in mongoose, so that this will be efficent while quering HOT 3
- incorrect for loop in cast HOT 4
- mongoose.model.ModelName disrupts types HOT 8
- Mongoose v6.12.6 installing optional dependencies @aws-sdk packages via mongodb 4.17.2 HOT 6
- update from version 6.11.6 to 7.4.0 there is a problem with the query HOT 4
- Virtuals not serialized after v8.5 HOT 3
- Cursor.next can return null, but TypeScript says it can't
- `this` context in nested schema `required` functions changed since mongoose 7.0.2+ HOT 2
- mongoose.connection.db can be undefined, but TypeScript says it can't HOT 3
- Connection Error and not getting any data - DEP0170 HOT 3
- Intersection type error in embedded schema when iterating through an embedded array HOT 3
- Populate + lean + multiple populated documents leads to "Cannot read properties of undefined (reading '_id')" in version 8.5.2 HOT 1
- After replica election, mongoose can't connect to mongo db and throw timeout error each 30s HOT 4
- Issue deleted
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mongoose.