简体   繁体   中英

MongoDB Deeply Nested

I have some difficulties with deeply nested arrays within MongoDB. I am using mongoose and my project consists of micro-services that all currently use the same database collection. Is it possible to use the below example with how deeply nested it is? If so, how would one access the "questionUser" , "questionTitle" , or "questionContent" . I currently am able to add course and lesson titles. when I am trying to add question data the correct router is getting hit, but it just hangs and times out and all the data going through is null .

I have condensed the data example below. I am working with MEAN stack. I also am not seeing any errors, it is just hanging. Not sure where or how to start troubleshooting this. I am not against redesigning my DB, but would like to keep with nested/embedded structure somehow but would need a little guidance on how I might look to change it.

Database

{
 "_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!"
                        }
                        ]
                }
                ]
        }
        ]
    }
  ]
}

Routers

/*
 * 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);

There are definitely ways to do operations on such kind of nested MODEL.

LIKE

for finding document mongoose provide POPULATE scheme and event better AGGREGATION.

When creating the document, I don't think there will be a problem. When updating the document you need _id of the sub and sub-sub document.

Ex of ID() function of mongoose

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.) This works fine but it also decrease the performance because it fetch whole document then rewrite it so SO better is not to use such kind of operation, 2.) Also remember the 16MB limitation/document

There are other ways to increase the performance ==> REFERENCE MODEL

you can design your model from one collection to TWO or may be THREE in reference system and can use feature of aggregation for referencing systems Aggrigation docs of mongodb , Populate of Mongoose

Hope this will help.. Thank you

You'll need to access them in this manner:

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

Just modify the last key name for other keys on the same level as the example.


MongoDB's support for updating nested arrays is poor. So you're best off avoiding their use if you need to update the data frequently and consider using multiple collections instead. However, there's a debate on this as well. You can read more on Embed vs Reference and decide what suits your needs the best.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM