Thought I'd check out node a couple days back and decided to create a simple API as an introduction to the platform. I am using node with express and mongoose. My issues at the moment revolve around trying to get a single subdocument from an array of subdocuments in my primary document.
My app has a simple structure. I have three models: place, address, and people. Each place embeds many addresses, and each address embeds many people (I picked this to get practice on subdocuments, and sub-subdocuments). The models themselves are separated into their own files as such:
./models/place.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var AddressSchema = require('./address')
var PlaceSchema = new Schema({
name: String,
addresses: [AddressSchema.Schema]
});
module.exports = mongoose.model('Place', PlaceSchema);
.models/address.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var PersonSchema = require('./person');
var AddressSchema = new Schema({
street: String,
city: String,
state: String,
zip: Number,
people: [PersonSchema.Schema]
});
module.exports = mongoose.model('Address', AddressSchema);
.models/person.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var PersonSchema = new Schema({
name: String,
});
module.exports = mongoose.model('Person', PersonSchema);
As we can see, a place can contain an array of addresses, and each address can contain an array of people.
Now as far as the my actual routes are concerned, I have no issue adding places, and adding addresses to places (I haven't drilled down to the person level as of yet). The issue I am having is trying to get a single address. I am thinking once I receive a single address, I can next assign a bunch of people to that address.
Here is the route that is causing trouble:
router.route('/places/:place_id/addresses/:address_id')
.get(function(req, res) {
Place.findById(req.params.place_id, function(err, place) {
if (err)
res.send(err);
res.json(place.addresses.id(req.params.address_id));
});
});
From the mongoose docs, it looks like the .id() method is the goto in this situation, but I get a "TypeError" when doing this, with logs saying that the object has no method 'id'.
On the other hand, I am having zero issue getting all the addresses of a single place:
router.route('/places/:place_id/addresses')
.get(function(req, res) {
Place.findById(req.params.place_id, function(err, place) {
if (err)
res.send(err);
res.json(place.addresses);
});
})
I also have zero issue creating and saving places, creating and saving addresses to a place, etc.
I've tried to dig and find others with a similar issue. I've found others who have experienced the same type error, but typically it has had to do with the order of initialization of their models. Most seem to be initializing their models in one big document, in which order of initialization is important. I do not understand how that would be an issue here?
Hopefully this is just me doing something stupid as I'm pretty stumped. Any help is very much appreciated.
EDIT----------------------------------------------------------------------------------------------
I'm thinking my problems are revolving around the id value of my :address_id parameter in the GET request above.
Taking some inspiration from this post:
MongoDB, Mongoose: How to find subdocument in found document?
I updated my get function to the following (though I do not know why what I had initially isn't working):
router.route('/places/:place_id/addresses/:address_id')
.get(function(req, res) {
Place.findById(req.params.place_id, function(err, place) {
if (err)
res.send(err);
var address = place.addresses.filter(function (address) {
return address._id === req.params.address_id;
}).pop();
res.json(address);
});
});
If instead of ._id I use .city for example to filter my addresses, then I return the correct addresses in the total array. Obviously this is not what I'm looking for. I'd like the return an address based on its ID.
Any help is appreciated.