猫鼬中相互文档引用的问题

时间:2018-12-26 09:03:17

标签: javascript mongodb express mongoose

我到处都想找到一种在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数组为空!!!

1 个答案:

答案 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}},以确保您实际上更新了数据库,不仅返回了一个过时的对象,而且该对象没有持久化到数据库中)。如果您真的对为什么会发生这样的事情感兴趣,请考虑只用最小的问题代码为这个问题创建一个新的,更具体的问题。