我到处都想找到一种在Mongoose中相互引用文档的方法。但是,包括Populate在内的所有文档都只有将一个文档的objectID保存在另一个文档中的示例。考虑到我有一个父级文档(“类别”)和多个子级文档(“子类别”),并且我想在子级中引用父级,反之亦然。我该怎么办?
我想到的最后一件事是在将文档保存到数据库之前添加objectID引用。这是该代码:
类别架构:
let mongoose = require("mongoose")
let categorySchema = new mongoose.Schema({
name: String,
sale_type: String,
sub_categories: [{type: mongoose.Schema.Types.ObjectId, ref:
"SubCategory" }]
})
module.exports = mongoose.model("Category", categorySchema)
子类别架构:
let mongoose = require("mongoose")
let subcategorySchema = new mongoose.Schema({
name: String,
sale_type: String,
category: {type: mongoose.Schema.Types.ObjectId, ref: "Category" }
})
module.exports = mongoose.model("SubCategory", subcategorySchema)
主文件:(此路线旨在创建新的“类别”)
app.post("/categories", function(req, res){
let name = req.body.name
let sale_type = req.body.sale_type
let sub_categories = req.body.sub_categories.split(",")
let category = new Category({
_id: new mongoose.Types.ObjectId(),
name: name,
sale_type: sale_type,
sub_categories: []
})
sub_categories.forEach(function(element){
let sub_category = new SubCategory({
_id: new mongoose.Types.ObjectId(),
name: element,
sale_type: sale_type,
category: category._id
})
sub_category.save(function(err, subcat){
if (err){
console.log(err);
res.status(500).send("")
} else {
category.sub_categories.push(subcat._id)
}
})
})
category.save(function(err, cat){
if (err){
console.log(err)
res.status(500).send("")
} else {
res.status(200).json(cat)
}
})
})
发生的尴尬事情是,当我按“ / categories”路线创建新类别时,这就是我从服务器获得的响应,而这正是我想要的:
{
"sub_categories": [
"5c2340bf4641017050567fe8",
"5c2340bf4641017050567fea"
],
"_id": "5c2340bf4641017050567fe6",
"name": "cat",
"sale_type": "retail",
"__v": 0
}
但是当我使用mongo shell查找类别时,这实际上是保存在数据库中的内容:
{ "_id" : ObjectId("5c2340bf4641017050567fe6"), "sub_categories" : [ ],
"name" : "cat", "sale_type" : "retail", "__v" : 0 }
并且sub_categories数组为空!!!
答案 0 :(得分:0)
您问了两个问题,这是我的第一个问题,涉及相互引用文档:
除非您知道子类的数量非常有限,否则不要使用数组来存储引用。如果子类别可以无限增长,则稍后可能会遇到性能问题。 (例如,有关详细信息,请参见this文章)
自从猫鼬4.5起,就有一个很棒的功能称为“虚拟填充”,我认为这是对您的问题的更优雅的解决方案。为此,您只需在您的类别中创建一个虚拟字段,即可自动为其获取子类别数组,如下所示:
// a `ref` property is how you enable virtual population
Category.virtual('subcategories', {
localField: '_id',
ref: 'Subcategory',
foreignField: 'category'
});
如果以这种方式使用,类别集合中将不会保存任何实际字段,但是如果您正确查询文档,则可以使用它相同的方式,而不会出现保存引用数组的问题:< / p>
Category.find().populate('subcategories')
此处有关于该主题的精彩文章:http://thecodebarbarian.com/mongoose-virtual-populate
这也应该解决(或至少解决)您的第二个问题,因为该字段不再持久化到数据库。为什么它不显示我不知道的数据,但我相信您应该可以通过添加以下代码来进行调试:首先验证代码中是否已将正确的数据写入db(例如,在返回数据之前,运行{{ 1}},以确保您实际上更新了数据库,不仅返回了一个过时的对象,而且该对象没有持久化到数据库中)。如果您真的对为什么会发生这样的事情感兴趣,请考虑只用最小的问题代码为这个问题创建一个新的,更具体的问题。