0

UPDATED: Thanks to everyone for the help

I'm getting 2 collections from Firestore: Roles and Apps. Apps is a subcollection of Roles so it is contained inside of Roles collection, therefore, to get the apps I need to get the Roles document where they are contained first. I have no problem doing this but I need to save them as they are stored in firebase to group them later, I can't figure out how. I want some data like this:

[
  {
    roleDescription: 'System Administrator',
    active: true,
    roleId: '1'
    apps: [
       { 
       appId: '2',
       appDescription: 'Manage Roles',
       groupId: '1',
       route: 'roles',
       appName: 'Roles',
       active: true
       },
       { 
       appId: '1',
       appDescription: 'Users',
       groupId: '1',
       route: 'users',
       appName: 'Users',
       active: true
       },
       {
        ...
       }
    ]
  },
  {
    active: true,
    roleId: '2',
    roleDescription: 'Employee',
    apps: [
       { 
       appId: '5',
       appDescription: 'Upload Data',
       groupId: '1',
       route: 'roles',
       appName: 'Roles',
       active: true
       },
       { 
       appId: '1',
       appDescription: 'Users',
       groupId: '1',
       route: 'users',
       appName: 'Users',
       active: true
       },
       {
        ...
       }
    ]
  }
]

Currently I have this code where I can get all the roles in snapshot and map them to get every role individually and then with snapshot2 get the apps that are contained inside that role also individually to assign every app in snapshot2 to to the object or array of roles contained also in an array.

Here is my code:

ref.get()
.then(function(snapshot) {
    return Promise.all(snapshot.docs.map(doc => {
        var AppRole = {};   
        AppRole.role = doc.data();  
        roles.push(AppRole); 
        return doc.ref.collection('apps').get()
        .then((snapshot2) => {
            return snapshot2.docs.map(app => {
                roles[count].apps = app.data(); // Here I need to push app.data() to roles[count].apps and problem solver but I don't know how to do it (roles[count].apps is an object and I know it doesnt have the push method but I tried with a counter also like roles[count].apps[i] = app.data(); i++; but no success )
            })
        })
        console.log(count);
        count++;
    }))
    .then(() => {
        console.log(roles);
        res.render("pages/roles", { name: req.session.name, idiom: req.session.idiom, roles: roles, apps: apps, pageInfo: req.session.lang.roles});
    })
2
  • Could you explain in a bit more details what you exactly want to achieve? It is not easy to understand, neither from your intro nor from your code. Commented Aug 8, 2018 at 7:17
  • I edited the question, thanks for your response! Commented Aug 8, 2018 at 12:39

2 Answers 2

1

You should be able to do this without any counters. I've commented the main changes in the code.

Basically, just keep a reference to the role after you create it. Then you can assign a list of apps to it all at once by using map().

const roles = []; // You can add and remove elements to a const array
const db = admin.firestore();
const ref = db.collection('roles');

ref.get()
.then(function(roleQuery) {
    return Promise.all(roleQuery.docs.map(roleDoc => {
        // ** Create a new role and keep a reference to it **
        const role = roleDoc.data()
        roles.push(role);
        return roleDoc.ref.collection('apps').get()
        .then((appQuery) => {
            // ** Easily create a new array by calling 
            // ** map() on the app documents
            role.apps = appQuery.docs.map(appDoc => {
                return appDoc.data();
            })
            // ** alternate syntax: 
            // ** appQuery.docs.map(appDoc => appDoc.data())
        })
    }))
    .then(() => {
        console.log(roles);
        res.render("pages/roles", { name: req.session.name, idiom: req.session.idiom, roles: roles, apps: apps, pageInfo: req.session.lang.roles});
    })
Sign up to request clarification or add additional context in comments.

3 Comments

I think I'm actually getting what I wanted but role.apps are appearing undefined where they got mapped, tried to add a promise behind the final map but no luck! Any idea why? Thank you! @cal2u
Forgot the return inside of map(). Let me know if this fixes it.
Fixed! Thank you very much, this seems so simple but I'm kinda new at JavaScript, have a great day!
1

Don't really understand the full scope of your code, but why not just create an object that assigns apps to roles, and store the end result in the roles array?

You shouldn't need the j counter in this instance. I would imagine it looks something like this:

let roles = [];
const count = 0;
const db = admin.firestore();
const ref = db.collection('roles');

ref.get()
.then(function(querySnapshot) {
    return Promise.all(querySnapshot.docs.map(doc => {
        var AppRole = {};   //Declare AppRole object
        AppRole.role = doc.data();   //Based on your question, this should return one role
        roles.push(AppRole);  //Adds object to array (You can use 'roles[count] = AppRole' if you feel more comfortable)
        return doc.ref.collection('apps').get()
        .then((snapshot2) => {
            return snapshot2.docs.map(app => {
                roles[count].apps = app.data(); //Based on your question, this should return an array of apps. That array should be stored within that particular object.
            })
        })
        console.log(count);
        count++;
    }))
    .then(() => {
        console.log(roles);
        res.render("pages/roles", { name: req.session.name, idiom: req.session.idiom, roles: roles, apps: apps, pageInfo: req.session.lang.roles});
    })

1 Comment

This helped me a lot! But app.data() is a single app not an array that's why im mapping snapshot2.docs to get all the apps and then I want to push every app.data() in roles[count].apps but i can´t find a way yet, thanks for your time!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.