У меня есть сценарий использования, в котором я хочу определить схему с виртуальной, а затем использовать эту схему в нескольких местах. Для этого я нашел свойство .add в документации mongoose, как показано здесь .
Поведение это не то, что я ожидаю, хотя по умолчанию виртуальное не заполняется. Я посмотрел на конкретную сгенерированную схему и обнаружил, что после ее создания с помощью «.add» она не сохраняет все поля исходной схемы. В частности, в объекте "virtuals" свойство "path" становится пустым объектом вместо строки, а в объекте "tree" виртуальное отсутствует вообще.
Я просмотрел фактическую зависимость и обнаружил, что эторезультат того, как «.add» работает внутри, а именно вызывает функцию «слияние», которая копирует многие свойства в новую схему. Примечательно, что функция слияния ничего не делает с объектом «дерево» в схеме, а в случае виртуалов она копирует имя / options / getters / setters, но ничего не делает для «пути». Я вручную добавил недостающие части в функцию слияния, и это исправило мою проблему, но я хотел бы знать, просто ли я использую это неправильно или это ошибка в библиотеке mongoose, поскольку непосредственное обновление зависимости не являетсяправильное решение для меня.
Вот пример того, как я создаю экземпляры схем
const testBase= data.db.Schema({
test: {type: String, required: true}
});
testBase.virtual('testVirtual')
.get(function () {
return "test";
});
testBase.set('toObject', {virtuals: true});
testBase.set('toJSON', {virtuals: true});
const testParent = data.db.Schema();
testParent.add(testBase);
testParent.set('toObject', {virtuals: true});
testParent.set('toJSON', {virtuals: true});
В этом примере, если я использую "testBase" в качестве моей схемы в модели, она будет правильно использоватьвиртуальный, в то время как если я использую «testParent», он не будет. Когда я ожидаю, что они должны вести себя одинаково.
Получение JSON двух схем показывает это для testBase
{
"$id": 24,
"_indexes": [],
"_userProvidedOptions": {
"toJSON": {
"virtuals": true
},
"toObject": {
"virtuals": true
}
},
"aliases": {},
"callQueue": [],
"childSchemas": [],
"inherits": {},
"methodOptions": {},
"methods": {},
"nested": {},
"obj": {
"test": {
"required": true
}
},
"options": {
"_id": true,
"autoIndex": null,
"bufferCommands": true,
"capped": false,
"discriminatorKey": "__t",
"id": true,
"minimize": true,
"noId": false,
"noVirtualId": false,
"read": null,
"shardKey": null,
"strict": true,
"toJSON": {
"virtuals": true
},
"toObject": {
"virtuals": true
},
"typeKey": "type",
"validateBeforeSave": true,
"versionKey": "__v"
},
"paths": {
"_id": {
"$immutable": null,
"_index": null,
"getters": [],
"instance": "ObjectID",
"options": {
"auto": true
},
"path": "_id",
"setters": [
null
],
"validators": []
},
"test": {
"$immutable": null,
"_index": null,
"enumValues": [],
"getters": [],
"instance": "String",
"isRequired": true,
"options": {
"required": true
},
"originalRequiredValue": true,
"path": "test",
"regExp": null,
"setters": [],
"validators": [
{
"message": "Path `{PATH}` is required.",
"type": "required"
}
]
}
},
"plugins": [],
"query": {},
"s": {
"hooks": {
"_posts": {},
"_pres": {}
}
},
"singleNestedPaths": {},
"statics": {},
"subpaths": {},
"tree": {
"_id": {
"auto": true
},
"test": {
"required": true
},
"testVirtual": {
"getters": [
null
],
"options": {},
"path": "testVirtual",
"setters": []
}
},
"virtuals": {
"testVirtual": {
"getters": [
null
],
"options": {},
"path": "testVirtual",
"setters": []
}
}
}
И это для testParent
{
"$id": 25,
"_indexes": [],
"_userProvidedOptions": {
"toJSON": {
"virtuals": true
},
"toObject": {
"virtuals": true
}
},
"aliases": {},
"callQueue": [],
"childSchemas": [],
"inherits": {},
"methodOptions": {},
"methods": {},
"nested": {},
"options": {
"_id": true,
"autoIndex": null,
"bufferCommands": true,
"capped": false,
"discriminatorKey": "__t",
"id": true,
"minimize": true,
"noId": false,
"noVirtualId": false,
"read": null,
"shardKey": null,
"strict": true,
"toJSON": {
"virtuals": true
},
"toObject": {
"virtuals": true
},
"typeKey": "type",
"validateBeforeSave": true,
"versionKey": "__v"
},
"paths": {
"_id": {
"$immutable": null,
"_index": null,
"getters": [],
"instance": "ObjectID",
"options": {
"auto": true
},
"path": "_id",
"setters": [
null
],
"validators": []
},
"test": {
"$immutable": null,
"_index": null,
"enumValues": [],
"getters": [],
"instance": "String",
"isRequired": true,
"options": {
"required": true
},
"originalRequiredValue": true,
"path": "test",
"regExp": null,
"setters": [],
"validators": [
{
"message": "Path `{PATH}` is required.",
"type": "required"
}
]
}
},
"plugins": [],
"query": {},
"s": {
"hooks": {
"_posts": {},
"_pres": {}
}
},
"singleNestedPaths": {},
"statics": {},
"subpaths": {},
"tree": {
"_id": {
"auto": true
},
"test": {
"required": true
}
},
"virtuals": {
"testVirtual": {
"getters": [
null
],
"options": {},
"path": {},
"setters": []
}
}
}
Если вы сравните отсутствующие схемы, вы увидите, какие поля отсутствуют. Если кто-нибудь знает правильный способ использования этой функциональности или примеров в этом направлении, я был бы признателен. (Мое тестирование проводилось с версией mongoose 5.7.8)