santiago
santiago

Reputation: 33

populate nested array of nested ref

The structure of the project is

structure

The main file is index.js that is located in the main directory. This one has

'use strict'

var mongoose = require('mongoose');
var app = require('./app');

var port = process.env.port || 3000;

mongoose.connect('mongodb://localhost:27017/changeProducts',(err,res) =>{
    if(err){
        throw err;
    }else{
        console.log("Base de datos funcionando correctamente..");

        app.listen(port, function(){
            console.log('Servidor nodejs corriendo(app.listen)... ');
        });

    }
});

The version of mongoose is 5.0

The app.js is

'use strict'

var express = require('express');
var bodyParser = require('body-parser');

var app = express();

//carga de rutas
//cr
var roleRoutes = require('./routes/cr/role');
var userRoutes = require('./routes/cr/user');
var loginRoutes = require('./routes/cr/login');
//category
var categoryRoutes = require('./routes/cr/category');

//publication
var publicationRoutes = require('./routes/publication/publication');
var offerRoutes = require('./routes/publication/offer');



app.use(bodyParser.urlencoded({
    extended: false
}));

app.use(bodyParser.json());

//configurar cabeceras
app.use((req, res, next)=>{
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'X-API-KEY, Origin, X-Requested-With','Content-Type, Accept, Access-Control-Request-Method');
    res.header('Access-Control-Allow-Method', 'GET, POST, OPTIONS, PUT, DELETE');
    res.header('Allow', 'GET, POST, OPTIONS, PUT, DELETE');

    next();
});


//rutas base
//cr
app.use('/api', roleRoutes);
app.use('/api', userRoutes);
app.use('/api', loginRoutes);
app.use('/api', categoryRoutes);

//publication
app.use('/api', publicationRoutes);
app.use('/api', offerRoutes);


module.exports = app;

the routes like userRoutes are in the folder routes.

the first route is routes/cr/category.js

'use strict'

var express = require('express');
var CategoryController = require('../../controllers/cr/category');
var api = express.Router();
var middlewareSecurity = require('../../security/middleware');

api.get('/categories', CategoryController.getCategories );

module.exports = api;

the other one is routes/cr/user.js

'use strict'

var express = require('express');
var UserController = require('../../controllers/cr/user');
var api = express.Router();
var middlewareSecurity = require('../../security/middleware');

//api.get('/users/',middlewareSecurity.HasRole("admin,user"), UserController.getUsers );

//actions of user
api.get('/users/', UserController.getUsers);
api.get('/user/:id', UserController.getUser);
api.post('/user', UserController.saveUser);
api.put('/user/:id', UserController.updateUser);
api.delete('/user/:id', UserController.deleteUser);

module.exports = api;

The schemas are in models/cr

the first schema that is located in 'models/category.js' is

'use strict'

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var CategorySchema = Schema({
    name: String,
    subcategories: [{
        name: String
    }]
});

module.exports = mongoose.model('Category',CategorySchema);

The other Schema is UserSchema and it looks like this

 'use strict'

    var mongoose = require('mongoose');
    var Schema = mongoose.Schema;


    var UserSchema = Schema({
        firstName: {
            type: String,
            required: true
        },
        secondName: String,
        lastName: {
            type: String,
            required: true
        },
        email: {
            type: String,
            unique: true,
            required: true
        },
        password: {
            type: String,
            required: true
        },
        status: {
            type: String,
            required: true
        },
        roles: [{
            type: Schema.ObjectId,
            ref: 'Role'
        }],

        publications: [{
            title: {
                type: String,

            },
            description: String,
            status: {
                type: String,

            },
            createdAt: {
                type: Date
            },
            updatedAt: {
                type: Date,
                default: Date.now()
            },

            pictures: [{
                name: String
            }],

            categories: [{
                type: Schema.Types.ObjectId,
                refPath: 'Category'
            }],

            publicationOffers: [{
                idpublication: [{
                    type: Schema.ObjectId,
                    ref: 'User.publications'
                }],
                iduser: {
                    type: Schema.ObjectId,
                    ref: 'User'
                },
                createdAt: {
                    type: Date
                }
            }]
        }]
    });


    module.exports = mongoose.model('User', UserSchema);

I have a plugin called mongooseeder mongooseeder

In order to start I run in terminal

node seeds.

this create some data of category.

after I run

npm start(remember to install dependencies with npm install)

the file controllers/cr/user.js has

'use strict'

var User = require('../../models/cr/user');
var bcrypt = require('bcrypt');
var path = require('path');
var fs = require('fs');

and one of the functions is

   function getUsers(req, res) {

        var find = User.find({}).sort('-firstName');

        find.exec((err, users) => {
            if (err) {
                res.status(500).send({
                    message: "Error en la peticion"
                });
                return;
            }

            if (!users) {
                res.status(404).send({
                    message: "no hay users"
                });
                return;
            }

            User.populate(users, {
                path: 'publications.categories'
            }, (err, users) => {

                if (err) {
                    res.status(500).send({
                        message: "Error en la peticion"
                    });
                    return;
                }

                if (!users) {
                    res.status(404).send({
                        message: "User no encontrado"
                    });
                    return;
                }


                res.status(200).send({
                    users
                });


                // var options = {
                //     path: 'publications.categories',
                //     select: 'subcategories.name'
                // };

                // if (err) {
                //     res.status(200).send({
                //         users
                //     });
                // }
                // User.populate(users, options, function (err, users) {
                //     res.status(200).send({
                //         users
                //     });
                // });

            });
        });
    }

module.exports = {
    getUser,
    getUsers,
    saveUser,
    updateUser,
    deleteUser
}

this method is used by routes/cr/user.js this contains(look the description where is the route and what contains) api.get('/users/', UserController.getUsers);

The link http://localhost:3000/api/users show this

{
    "users": [
        {
            "roles": [
                "5ae4a8b0a7510e3bd80917d5"
            ],
            "publications": [],
            "_id": "5ae79ee4b34bea810861ccc5",
            "firstName": "santiago4",
            "lastName": "torres3",
            "email": "[email protected]",
            "status": "activo",
            "password": "$2b$10$rONv8dlZVOMJ4kU1x4XUmuVeTiyl.B.IVrIIlPDHz.0Yuqh5w05wK",
            "__v": 0
        },
        {
            "roles": [],
            "publications": [
                {
                    "updatedAt": "2018-04-30T03:23:11.921Z",
                    "categories": [
                        "5ae4a8b0a7510e3bd80917db",
                        "5ae4a8b0a7510e3bd80917da"
                    ],
                    "pictures": [],
                    "publicationOffers": [],
                    "_id": "5ae68cbf7cda345ec0b910f3",
                    "title": "publicacio2",
                    "description": "descripcion2",
                    "status": "activo",
                    "createdAt": "2018-04-30T03:25:51.053Z"
                },
                {
                    "updatedAt": "2018-04-30T03:45:14.159Z",
                    "categories": [
                        "5ae4a8b0a7510e3bd80917db"
                    ],
                    "pictures": [],
                    "publicationOffers": [],
                    "_id": "5ae692183670e54b9c529698",
                    "title": "publicacio2",
                    "description": "descripcion2",
                    "status": "activo",
                    "createdAt": "2018-04-30T03:48:40.654Z"
                },
                {
                    "updatedAt": "2018-04-30T04:01:23.131Z",
                    "categories": [
                        "5ae4a8b0a7510e3bd80917db"
                    ],
                    "pictures": [],
                    "publicationOffers": [],
                    "_id": "5ae6956d9e15516ccceb13d8",
                    "title": "publicacio2",
                    "description": "descripcion2",
                    "status": "activo",
                    "createdAt": "2018-04-30T04:02:53.177Z"
                }
            ],
            "_id": "5ae689f9a67a6284f4af4033",
            "firstName": "santiago3",
            "lastName": "torres3",
            "email": "[email protected]",
            "status": "activo",
            "password": "$2b$10$ge1lS.r/eV1nJRkQDi4dn.0AQKpJfI.a5GzBlpsN5trHefVRVjVCS",
            "__v": 0
        },
        {
            "roles": [],
            "publications": [],
            "_id": "5ae689f0a67a6284f4af4032",
            "firstName": "santiago2",
            "lastName": "torres2",
            "email": "[email protected]",
            "status": "activo",
            "password": "$2b$10$HND7lixmr5RT4A/Kz5gv6.it9kmHpauytIHw/UydgTOAwkbNTJf8O",
            "__v": 0
        },
        {
            "roles": [],
            "publications": [],
            "_id": "5ae689e5a67a6284f4af4031",
            "firstName": "santiago1",
            "lastName": "torres1",
            "email": "[email protected]",
            "status": "activo",
            "password": "$2b$10$.sNgBlSerC6f19Hd2.xnzOtpUAd8BB9JXXM5BlGIvr0dUhWOtn5IS",
            "__v": 0
        }
    ]
}

the file controllers/cr/category.js has

'use strict'

var Categories = require('../../models/cr/category');


function getCategories(req, res){

    Categories.find({},(err, categories) =>{
        if(err){
            res.status(500).send({ message: 'Error en la peticion' });
            return;   
        }

        if(!categories){
            res.status(404).send({ message: 'No hay categories' });
            return
        }

        res.status(200).send({ categories });
    });
}


module.exports = {
    getCategories
}

this method is used by routes/cr/category.js this contains(look the description where is the route and what contains)

'use strict'

var express = require('express');
var CategoryController = require('../../controllers/cr/category');
var api = express.Router();
var middlewareSecurity = require('../../security/middleware');

api.get('/categories', CategoryController.getCategories );

module.exports = api;

http://localhost:3000/api/categories will show this json

{
    "categories": [
        {
            "subcategories": [
                {
                    "_id": "5ae4a8b0a7510e3bd80917db",
                    "name": "Decoracion"
                },
                {
                    "_id": "5ae4a8b0a7510e3bd80917da",
                    "name": "Electrodomésticos"
                },
                {
                    "_id": "5ae4a8b0a7510e3bd80917d9",
                    "name": "Cocina"
                },
                {
                    "_id": "5ae4a8b0a7510e3bd80917d8",
                    "name": "Muebles"
                }
            ],
            "_id": "5ae4a8b0a7510e3bd80917d7",
            "name": "Hogar",
            "__v": 0
        },
        {
            "subcategories": [
                {
                    "_id": "5ae4a8b0a7510e3bd80917e0",
                    "name": "Computador escritorio"
                },
                {
                    "_id": "5ae4a8b0a7510e3bd80917df",
                    "name": "Laptop"
                },
                {
                    "_id": "5ae4a8b0a7510e3bd80917de",
                    "name": "Celulares"
                },
                {
                    "_id": "5ae4a8b0a7510e3bd80917dd",
                    "name": "Tablets"
                }
            ],
            "_id": "5ae4a8b0a7510e3bd80917dc",
            "name": "Tecnología",
            "__v": 0
        }
    ]
}

I need to populate categories of UserSchema referencing subcategories of CategorySchema(See Schemas mentioned before). If you see in the file controllers/cr/user.js there is

User.populate(users, {
            path: 'publications.categories'
        }, (err, users) => {....

currently the UserSchema contains this

categories: [{
                type: Schema.Types.ObjectId,
                refPath: 'Category'
            }],

I am trying to do something like this

 categories: [{
                type: Schema.Types.ObjectId,
                refPath: 'Category.subcategories'
            }],

categories is inside of publications(see schemas mentioned before)

I need to get something like this

"publications": [
                {
                    ...
                    "categories": [
                        {
                          "_id": "5ae4a8b0a7510e3bd80917db",
                          "name": "subcategory1"
                        },
                        {
                           "_id": "5ae4a8b0a7510e3bd80917da",
                           "name": "subcategory2"
                        }
                    ]

                },
                {
                    ....
                    "categories": [
                        {
                           "_id": "5ae4a8b0a7510e3bd80917e0",
                           "name": "subcategory1"
                        }
                    ]                
                },
    ]

but it's showing me this in publications of UserSchema

"publications": [
            {
                ...
                "categories": [
                    "5ae4a8b0a7510e3bd80917db",
                    "5ae4a8b0a7510e3bd80917da"
                ]

            },
            {
                ...
                "categories": [
                    "5ae4a8b0a7510e3bd80917e0"
                ]                
            },
]

publications is inisde of UserSchema(see UserSchema mentioned before)

this is the link to download the reporsitory where is the project link of reporsitory

Please help me whith this. I have been searching and trying a lot of things whithout success. I can't find a solution in the documentation, stackoverflow and other websites. Nothing works. I tried to use dinamic references of mongoose and that does not work. I tried to use this. https://github.com/buunguyen/mongoose-deep-populate

And I tried a lot of thing and none of them works. Please Help me!. I am a worry about it.

Upvotes: 0

Views: 182

Answers (0)

Related Questions