skip to Main Content

I have relative field and in relative I have subRelatives and it continues like nested array. Mean in subRelatives I have subRelatives and some time its 10 times continues process.

My code

router.get(`/userTree/:id`, async (req, res) => {
    const userTrees = await Tree.find({createdBy: req.params.id})
        .populate(
            ["createdBy",
                {
                    path: "relatives",
                    populate: {
                        path: "subRelatives",
                        populate: {
                            path: "subRelatives",
                            populate: "subRelatives",
                        },
                    },
                }
            ]);

    if (!userTrees) {
        res.status(500).json({success: false});
    }

    res.send({success: true, data: userTrees});
});

I have added populate but it populate first 2 sub relative and then shows MongooseIds only without populating. So I need to added manually some more populate methods so it will run but its crashing because of lot of data now.

and data look like this.

{
    "success": true,
    "data": {
        "_id": "62dad5c6aff2337dc84d9b40",
        "treeName": "test1",
        "createdBy": {
            "_id": "62d8619cebd6543477c5b7d8",
            "userName": "test1",
            "userEmail": "[email protected]",
            "userFamilyTrees": [
                "62d8c713547ba80854d89d59"
            ]
        },
        "relatives": [
            {
                "_id": "62dad5c7aff2337dc84d9b44",
                "firstName": "tesads",
                "subRelatives": [
                    {
                        "_id": "62db1cf186b7012ed9937517",
                        "firstName": "asdasd",
                        "subRelatives": []
                    },
                    {
                        "_id": "62db1d0d86b7012ed9937522",
                        "firstName": "asd",
                        "subRelatives": []
                    },
                    {
                        "_id": "62dc24c15e6f5ea436cce14b",
                        "firstName": "julia",
                        "subRelatives": [
                            {
                                "_id": "62dc24c15e6f5ea436cce14b",
                                "firstName": "julia",
                                "subRelatives": [
                                    "62dc253bd2119bea52f4f9af"
                                ]
                            }
                        ]
                    },
                    {
                        "_id": "62dc24fcd2119bea52f4f99d",
                        "firstName": "julia",
                        "subRelatives": []
                    }
                ]
            }
        ]
    }
}

This is my Tree Schema

const mongoose = require(‘mongoose’)

const treeSchema = new mongoose.Schema({
    treeName: {
        type: String,
        required: true
    }, image: {
        type: String,
        default: ''
    },
    treePrivacy: {
        type: Boolean,
        required: true
    },
    treeNote: {
        type: String,
        default: ""
    },
    createdBy: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'users',
        required: true,
    },
    createDate: {
        type: Date,
        default: Date.now,
    },
    relatives: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'relatives',
    },],
    usersInTree: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'users',
    },],
    media: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'media',
    },]
});



treeSchema.virtual('treeID').get(function () {
    return this._id.toHexString();
});

treeSchema.set('toJSON', {
    virtuals: true
})

exports.Tree = mongoose.model('trees', treeSchema)

exports.treeSchema = treeSchema;

This is relative Schema

const mongoose = require('mongoose')

const relativeSchema = new mongoose.Schema({
    firstName: {
        type: String,
    },
    lastName: {
        type: String,
    }, image: {
        type: String,
    },
    relativeEmail: {
        type: String,
    },
    relativeType: {
        type: Number,
    },
    // relative grandfather0, father1, mother2, wife3, sister4, brother5, child6
    treeID: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'users',
        required: true,
    },
    subRelatives: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'relatives',
    }],
    parentRelative: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'relatives',
    },
    userID: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'relatives',
        required: false
    }
});

relativeSchema.virtual('relativeId').get(function () {
    return this._id.toHexString();
});

relativeSchema.set('toJSON', {
    virtuals: true
})

exports.Relatives = mongoose.model('relatives', relativeSchema)

exports.relativeSchema = relativeSchema;

This is post api for tree

router.post('/createTree', uploadOptions.single('image'), async (req, res) => {
    const file = req.file;
    if (!file) return res.status(400).send('No image in the request');

    const fileName = file.filename;
    const basePath = `${req.protocol}://${req.get('host')}/public/uploads/`;
    var userintree = [];


    const userExist = await User.findById(req.body.createdBy);
    if (!userExist) return res.status(400).send({ success: false, message: 'UserID   is not correct' })
    userintree.push(req.body.createdBy);

    let createtree = new Tree({
        treeNote: req.body.treeNote,
        treeName: req.body.treeName,
        treePrivacy: req.body.treePrivacy,
        createdBy: req.body.createdBy,
        image: `${basePath}${fileName}`,
        usersInTree: userintree
    });

    createtree = await createtree.save();
    if (!createtree) return res.status(400).send({ success: false, message: 'Issue to create a tree' })


    userExist.userFamilyTrees.push(createtree._id.toHexString())
    const user = await User.findByIdAndUpdate(
        req.body.createdBy,
        {
            userFamilyTrees: userExist.userFamilyTrees,
            $push: {
                usersInTree: req.body.createdBy
            }

        },

        { new: true }
    )
    if (user) res.status(200).send({ success: true, message: 'Tree Created.!,', data: createtree })
});

and post API for relative

router.post('/addRelative', uploadOptions.single('image'), async (req, res) => {
    const file = req.file;
    if (!file) return res.status(400).send('No image in the request');

    const fileName = file.filename;
    const basePath = `${req.protocol}://${req.get('host')}/public/uploads/`;
    console.log(fileName); console.log(basePath);
    console.log(req.body);
    let createRelative = new Relatives({
        firstName: req.body.firstName,
        lastName: req.body.lastName,
        relativeEmail: req.body.relativeEmail,
        relativeType: req.body.relativeType,
        treeID: req.body.treeID,
        subRelatives: req.body.subRelatives,
        parentRelative: req.body.parentRelative, image: `${basePath}${fileName}`,

    });
    const treeExist = await Tree.findById(req.body.treeID);
    if (!treeExist) return res.status(400).send({ success: false, message: 'TreeID is not correct' })
    createRelative = await createRelative.save();
    if (!createRelative)
        return res.status(400).send({ success: false, message: 'Something Went Wrong.!,' })
    treeExist.relatives.push(createRelative._id.toHexString())

    const tree = await Tree.findByIdAndUpdate(
        req.body.treeID,
        {
            relatives: treeExist.relatives
        },
        { new: true }
    )

    if (req.body.parentRelative) {
        console.log(req.body.parentRelative)

        const parent = await Relatives.findById(
            req.body.parentRelative
        );
        // console.log(parent)
        // console.log(parent)

        parent.subRelatives.push(createRelative)
        const user = await Relatives.findByIdAndUpdate(
            req.body.parentRelative,
            {
                subRelatives: parent.subRelatives,
            },
            { new: true }
        )
        // console.log(user)
        if (!user) return res.status(400).send({ success: false, message: 'Something Went Wrong.!,' })

        // res.send(ser);
    }


    res.status(200).send({ success: true, message: 'Relative Created Created.!,', data: createRelative })
});

2

Answers


  1. Populate data like this

      .populate(
                ["createdBy",
                    {
                        path: "relatives",
                        populate: {
                            path: "subRelatives",
                            model: "SubRelative",
                        },
                    }
    
                ]);
    

    I’ve assumed that the model name refaring to subRelative is SubRelative

    Login or Signup to reply.
  2. mongoose does support nested population, it’s just that you need to specify the model field as the treeSchema does not have access to all other schema during run time. It looks like this:

    const userTrees = await Tree.find({createdBy: req.params.id})
        .populate(
            [
                "createdBy",
                {
                    path: "relatives",
                    populate: {
                        path: "subRelatives",
                        model: 'relatives',
                    },
                }
            ]);
    

    mongoose does some optimizations to the query, but considering you know the exact structure you can reduce db calls and improve performance if you do this yourself instead of using populate.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search