0

I'm using async each to iterate over objects and perform a query to populate their children. Each site has locations which have floors which have areas. My sites and locations populate just fine, however, that is where it stops. Sails outputs that it is looking for floors and areas though but they are never assigned. Any ideas?

gg: function (req, res) {
    var userID = req.param('id');

    User.findOne({ id: userID }).populate('sites').exec(function afterFind(err, foundUser) {
        if (err) return res.json({ status: 'failure', message: 'Server error' });
        if (foundUser === undefined) return res.json({ status: 'failure', message: 'User was not found' });

        var resultToJson = foundUser.toJSON();
        var sites = resultToJson.sites;

        async.each(sites, function (site, siteCb) {
            sails.log.debug('Finding locations for ' + site.name);
            Locations.find({ site: site.id }).exec(function afterFind(err, foundLocations) {
                if (err) {
                    siteCb(err);
                } else {
                    site['locations'] = foundLocations;

                    async.each(site['locations'], function (location, locCb) {
                        sails.log.debug('Finding floors for ' + location.name);
                        Floor.find({ location: location.id }).exec(function afterFind(err, foundFloors) {
                            if (err) {
                                locCb(err);
                            } else {
                                location['floors'] = foundFloors;

                                async.each(location['floors'], function (floor, floorCb) {
                                    sails.log.debug('Finding areas for ' + floor.name);
                                    Area.find({ floor: floor.id }).exec(function afterFind(err, foundAreas) {
                                        if (err) {
                                            floorCb(err);
                                        } else {
                                            floor['areas'] = foundAreas;
                                            floorCb();
                                        }
                                    });
                                }, function (floorError) {
                                    if (floorError) {
                                        locCb(floorError);
                                    }
                                    else {
                                        locCb();
                                    }
                                });
                            }
                        });
                    }, function (locError) {
                        if (locError) {
                            siteCb(locError);
                        } else {
                            siteCb();
                        }
                    });
                }
            });
        }, function (siteError) {
            if (siteError) {
                sails.log.debug(siteError);
                return res.json({ status: 'failure', message: 'Server error' });
            } else {
                return res.json({ status: 'success', message: 'Sites for user retrieved', sites: sites });
            }
        });
    });
}
Ben Brookes
  • 419
  • 4
  • 15

1 Answers1

0

This code should be fixed with use of toJSON() on foundLocations. Anytime when you're overriding a defined attribute with populated one (or something else) it will not work when using a ORM returned object, use toJSON() or something and assign to plain JS object.

Ref: https://stackoverflow.com/a/43500017/1435132

Also, any reason to not use populate with Locations.find?

Sangharsh
  • 2,999
  • 2
  • 15
  • 27
  • toJSON throws a type error. 'Not a function'. To use populate I would have to create a two way relationship between each level wouldn't I? Is this something you suggest? – Ben Brookes Jul 04 '17 at 08:45
  • `toJSON` can't be applied to array, can be applied to each object (returned by ORM). Bit out of touch to comment on 2-way relationship. – Sangharsh Jul 04 '17 at 08:48
  • I fixed this as per your suggestion. Iterating through the array and using toJSON before pushing. Thank you. – Ben Brookes Jul 04 '17 at 08:57