MongoDB深层嵌套

时间:2017-06-10 19:55:51

标签: node.js mongodb express mongoose

我在MongoDB中使用深层嵌套数组时遇到了一些困难。我使用的是mongoose,我的项目包含所有当前使用相同数据库集合的微服务。是否可以使用下面的示例来嵌套它有多深?如果是,那么如何访问"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);

2 个答案:

答案 0 :(得分:3)

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

LIKE

用于查找文件mongoose提供更好的聚合方案和事件AGGREGATION。

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

Mongoose的ID()函数的Ex

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);
});

CONS

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

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

您可以将模型从一个集合设计为 TWO ,或者可以在参考系统中 THREE ,并且可以使用聚合功能来引用系统 Aggrigation docs of mongodbPopulate of Mongoose

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

答案 1 :(得分:1)

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

  1. lessons.lessonTitle
  2. lessons.questions.questionUser
  3. lessons.questions.answers.answerUser
  4. lessons.questions.answers.comment.commentUser
  5. 只需修改与示例相同级别的其他键的最后一个键名称。

    MongoDB对更新嵌套数组的支持很差。因此,如果您需要经常更新数据并考虑使用多个集合,那么最好避免使用它们。但是,对此也存在争议。您可以在Embed vs Reference上阅读更多内容,并确定最适合您需求的内容。