PintOverflow
PintOverflow

Reputation: 135

How to output a 1 to many object using bookshelf js

I am using bookshelf and knex to connect to a PostgreSQL database. Im trying to retrieve data that has a one to many relationship. My database looks like this:

Table: athlete

|----------------------------|
|  id | firstname | lastname |
|----------------------------|
|  0  | john      | doe      |
|  1  | jane      | doe      |
|----------------------------|

Table: activity

|------------------------------------|
|  id | athlete_id | type | distance |
|------------------------------------|
|  0  |     1      | run  |    5     |
|  1  |     0      | walk |    7     |
|------------------------------------|

My bookshelf models look like this:

const Athlete = bookshelf.Model.extend({
    tableName: 'athlete',
    activities: function() {
        return this.hasMany('Activity', 'athlete_id');
    }
});

const Activity = bookshelf.Model.extend({
    tableName: 'activity',
    athlete: function() {
        return this.belongsTo('Athlete');
    }
});

Then I call Activity.fetchAll().then(...)

This returns

[
  {
    "id": "0",
    "athlete_id": "1",
    "type": "run",
    "distance": "5",
  },
  {
    "id": "1",
    "athlete_id": "0",
    "type": "walk",
    "distance": "7",
  }
]

What I want it to return is

[
  {
    "id": "0",
    "athlete": {
        "athlete_id": "1",
        "firstname": "jane",
        "lastname": "doe"
    },
    "type": "run",
    "distance": "5",
  },
  {
    "id": "1",
    "athlete": {
        "athlete_id": "0",
        "firstname": "john"
        "lastname": "doe"
    },
    "type": "walk",
    "distance": "7",
  }
]

I found this: Activity.fetch({withRelated: 'athlete'}).then(...) but that returns a 500 error for me with no message.

I need help trying to return a nested object.

Upvotes: 1

Views: 1151

Answers (2)

zerosand1s
zerosand1s

Reputation: 750

You are missing a pair of square brackets around athlete. That could be a possible thing causing this error.

Activity.fetch({withRelated: ['athlete']}).then(...)

EDIT

Hey @Derekedelaney, I tried to implement the same project and did not face any issues. You can find it here. I got the output like this

[
  { id: 1,
    athlete_id: 1,
    type: 'run',
    distance: '5',
    athlete: { id: 1, firstname: 'john', lastname: 'doe' } 
  },
  { id: 2,
    athlete_id: 2,
    type: 'walk',
    distance: '7',
    athlete: { id: 2, firstname: 'jane', lastname: 'doe' }
  } 
]

Please note that I am using Bookshelf registry plugin so go through that once. Let me know if you have any difficulty.

Upvotes: 1

flaviodesousa
flaviodesousa

Reputation: 7815

Your tables use non-standard primary keys, so you must specify them using the idAttribute property. Simply put change your models to:

const Athlete = bookshelf.Model.extend({
    tableName: 'athlete',
    idAttribute: 'athlete_id'
    activities: function() {
        return this.hasMany('Activity', 'athlete_id');
    }
});

const Activity = bookshelf.Model.extend({
    tableName: 'activity',
    idAttribute: 'activity_id'
    athlete: function() {
        return this.belongsTo('Athlete');
    }
});

Also getting just a plain 500 HTTP status is not helpful. I recommend you to add a catch clause to your fetch() code, something like:

Activity
  .fetch({withRelated: ['athlete']})
  .then(...)
  .catch(ex => {
     log.err('Error while fetching', ex); // or at least 'console.dir(ex)'
     throw ex;
  })

Upvotes: 1

Related Questions