【问题标题】:MongoDB Deeply NestedMongoDB 深度嵌套
【发布时间】:2017-06-10 19:55:51
【问题描述】:

我在 MongoDB 中使用深度嵌套的数组时遇到了一些困难。我正在使用猫鼬,我的项目由当前所有使用相同数据库集合的微服务组成。是否可以将下面的示例用于嵌套的深度?如果是这样,如何访问"questionUser""questionTitle""questionContent"。我目前可以添加课程和课程标题。当我尝试添加问题数据时,正确的路由器被击中,但它只是挂起并超时,并且通过的所有数据都是 null

我已经压缩了下面的数据示例。我正在使用 MEAN 堆栈。我也没有看到任何错误,它只是挂起。不知道从哪里或如何开始对此进行故障排除。我不反对重新设计我的数据库,但想以某种方式保持嵌套/嵌入式结构,但需要一些关于如何更改它的指导。

数据库

{
 "_id": "593bc9fbbc083a8200eb9b36",
  "courseTitle": "Course 101",
  "courseActive": true,
  "lessons": [
    {
      "lessonTitle": "Lesson about widgets",
      "_id": "593bcecc0799cd89a87ce53e",
      "lessonActive": true,
      "questions": [
        {
            "questionUser": "user1",
            "_id" : "dadsfjlkj23o21",
            "questionTitle": "title",
            "questionContent": "stuffff",
            "answers" : [
                {
                    "answerUser": "user2",
                    "_id": "asdfk231191837d",
                    "answerContent": "the answer is simple",
                    "comment": [
                        {
                            "commentUser": "user1",
                            "_id": "asdkjfawow8183",
                            "commentBody": "That makes sense, thanks!"
                        }
                        ]
                }
                ]
        }
        ]
    }
  ]
}

路由器

/*
 * create new course
 */
router.post('/', (req, res) => {
  let course = new Course();
  course.courseTitle = req.body.courseTitle;
  course.courseActive = req.body.courseActive;
  course.save().then((saveCourse) => res.json(saveCourse))
    .catch((err) => console.log(err));
});

/*
 * create new lesson
 */
router.post('/:id', (req, res) => {
  Course.findOne({_id: req.params.id}).then((foundCourse) => {
    foundCourse.lessons = req.body.lessons;
    foundCourse.save().then((savedCourse) => res.json(savedCourse))
      .catch((err) => console.log(err));
  })
});

/*
 * create new question
 */
 router.post('/:id/lessons/:lessonid', (req, res) => {
   Lesson.findOne({_id: req.params.id}).then((foundLesson) => {
     foundLesson.questions = req.body.questions;
     foundLesson.save().then((savedLesson) => res.json(savedLesson))
       .catch((err) => console.log(err));
   })
 });

app.ts

import courses from './api/courses';
app.use('/api/v2/courses', courses);

import lessons from './api/lessons';
app.use('/api/v2/lessons', lessons);

import questions from './api/questions';
app.use('/api/v2/questions', questions);

【问题讨论】:

  • 你可能应该展示你用来访问这个结构的代码,因为结构本身并没有告诉我们它为什么挂起。也就是说,你真的应该在 Mongoose 文档中查看populate,因为我认为你在使用这个模式时犯了一个错误。其中一些东西应该有自己的集合,并通过引用相互关联。
  • @Paul 我将编辑和更新帖子,谢谢...我原本不想在帖子中放置太多信息,而且看起来很混乱。我会在更新帖子后立即查看populate。谢谢!
  • 每当有人一味地提到填充时,我要求考虑你真正想要实现的目标Mongoose populate vs object nesting
  • 我的目标是有一个论坛(这只是为了练习),它有一个课程登陆页面,用户点击一个课程,这将把他们带到课程,课程到问题,问题到答案和 cmets。类似于堆栈溢出,只是在问题之前有一个课程和课程页面。如果课程或课程被删除,我希望删除任何内容中的所有数据。我在想 mongodb 是最好的,但我无法访问深度嵌套的数据。当它被引用时,我不知道如何删除被删除项目引用的数据。

标签: node.js mongodb express mongoose


【解决方案1】:

肯定有办法对这种嵌套的模型进行操作。

喜欢

为查找文档 mongoose 提供 POPULATE 方案和事件更好的 AGGREGATION。

创建文档时,我认为不会有问题。 更新文档时需要子和子子文档的_id。

猫鼬的 ID() 函数示例

Model.findOneById("").then((data) => {
    if (!data) return res.status(401).json({ "err": "not found" });

    var lesson = data.lessons.id("lessionId");
    if (!lesson) return res.status(401).json({ "err": "not found!!" });

    var question = lession.id("QustionId");
    if (!question) return res.status(401).json({ "err": "not found!!" });

    var answer = answer.id("AnswerId");
    if (!answer ) return res.status(401).json({ "err": "not found!!" });

    var comment = answer.id("commentId");
    if (!comment ) return res.status(401).json({ "err": "not found!!" });

    comment.commentUser: "user1",                   
    comment.commentBody: "That makes sense, thanks!"

    data.save().then((success) => {
        return res.status(200).json("success");
    }).catch((err) => {
        return res.status(500).json(err);
    });

}).catch((err) => {
    return res.status(500).jsonp(err);
});

缺点

1.) 这很好用,但也会降低性能,因为它会获取整个文档然后重写它,所以最好不要使用这种操作, 2.) 还要记住 16MB 限制/文档

还有其他方法可以提高性能 ==> 参考模型

您可以将模型从一个集合设计为 TWO 或在参考系统中可能是 三个,并且可以将聚合功能用于参考系统 Aggrigation docs of mongodb , Populate of Mongoose

希望这会有所帮助.. 谢谢

【讨论】:

    【解决方案2】:

    您需要以这种方式访问​​它们:

    1. lessons.lessonTitle
    2. lessons.questions.questionUser
    3. lessons.questions.answers.answerUser
    4. lessons.questions.answers.comment.commentUser

    只需修改与示例同级别的其他键的最后一个键名即可。


    MongoDB 对更新嵌套数组的支持很差。因此,如果您需要频繁更新数据并考虑使用多个集合,最好避免使用它们。不过,这方面也有争论。您可以在Embed vs Reference 上阅读更多内容,并确定最适合您需求的内容。

    【讨论】:

      猜你喜欢
      • 2018-11-17
      • 2019-05-05
      • 1970-01-01
      • 2013-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      相关资源
      最近更新 更多