Created
June 9, 2017 02:02
-
-
Save mattboutet/17c0789563732b8bcba98056b72315e0 to your computer and use it in GitHub Desktop.
Strange relate behavior with objection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//From https://www.vincit.fi/en/blog/effortless-eager-loading-nested-inserts-objection-js/ | |
//There's a bunch of code here that's not needed for this example, but I was trying to keep edits to a minimum | |
//Stick this in a directory, then `npm install objection knex sqlite3` | |
//to run: node app.js | |
//Changing reviewerId to reviewer in the code below will cause the problem I'm talking about | |
'use strict'; | |
const objection = require('objection'); | |
const Promise = objection.Promise; | |
const Model = objection.Model; | |
const knex = require('knex')({ | |
client: 'sqlite3', | |
connection: { | |
filename: './test.db' | |
} | |
}); | |
// Make all models use the same database. | |
Model.knex(knex); | |
// Create the tables. Normally this would be | |
// done using migration files. For simplicity, | |
// we create them in this same file. | |
const createSchema = Promise.coroutine(function *() { | |
yield knex.schema.dropTableIfExists('Movie'); | |
yield knex.schema.dropTableIfExists('Person'); | |
yield knex.schema.dropTableIfExists('Review'); | |
yield knex.schema.dropTableIfExists('Movie_Person'); | |
yield knex.schema.createTable('Movie', function (table) { | |
table.bigincrements('id').primary(); | |
table.string('name'); | |
}); | |
yield knex.schema.createTable('Person', function (table) { | |
table.bigincrements('id').primary(); | |
table.string('firstName'); | |
table.string('lastName'); | |
table.biginteger('parentId') | |
.references('id') | |
.inTable('Person') | |
.index(); | |
}); | |
yield knex.schema.createTable('Review', function (table) { | |
table.bigincrements('id').primary(); | |
table.string('title'); | |
table.integer('stars'); | |
table.string('text'); | |
table.biginteger('movieId') | |
.references('id') | |
.inTable('Movie') | |
.index(); | |
table.biginteger('reviewerId') | |
.references('id') | |
.inTable('Person') | |
.index(); | |
}); | |
yield knex.schema.createTable('Movie_Person',function(table){ | |
table.biginteger('movieId') | |
.references('id') | |
.inTable('Movie') | |
.index(); | |
table.biginteger('personId') | |
.references('id') | |
.inTable('Person') | |
.index(); | |
}); | |
}); | |
class Movie extends Model { | |
static get tableName() { | |
return 'Movie'; | |
} | |
static get relationMappings() { | |
return { | |
actors: { | |
relation: Model.ManyToManyRelation, | |
modelClass: Person, | |
join: { | |
from: 'Movie.id', | |
through: { | |
from: 'Movie_Person.movieId', | |
to: 'Movie_Person.personId' | |
}, | |
to: 'Person.id' | |
} | |
}, | |
reviews: { | |
relation: Model.HasManyRelation, | |
modelClass: Review, | |
join: { | |
from: 'Movie.id', | |
to: 'Review.movieId' | |
} | |
} | |
}; | |
} | |
} | |
class Review extends Model { | |
static get tableName() { | |
return 'Review'; | |
} | |
static get relationMappings() { | |
return { | |
reviewer: { | |
relation: Model.BelongsToOneRelation, | |
modelClass: Person, | |
join: { | |
from: 'Review.reviewerId', | |
to: 'Person.id' | |
} | |
}, | |
movie: { | |
relation: Model.BelongsToOneRelation, | |
modelClass: Movie, | |
join: { | |
from: 'Review.movieId', | |
to: 'Movie.id' | |
} | |
} | |
}; | |
} | |
} | |
class Person extends Model { | |
static get tableName() { | |
return 'Person'; | |
} | |
static get relationMappings() { | |
return { | |
parent: { | |
relation: Model.BelongsToOneRelation, | |
modelClass: Person, | |
join: { | |
from: 'Person.parentId', | |
to: 'Person.id' | |
} | |
}, | |
reviews: { | |
relation: Model.HasManyRelation, | |
modelClass: Review, | |
join: { | |
from: 'Person.id', | |
to: 'Review.reviewerId' | |
} | |
}, | |
movies: { | |
relation: Model.ManyToManyRelation, | |
modelClass: Movie, | |
join: { | |
from: 'Person.id', | |
through: { | |
from: 'Movie_Person.personId', | |
to: 'Movie_Person.movieId' | |
}, | |
to: 'Movie.id' | |
} | |
} | |
}; | |
} | |
} | |
const runQueries = Promise.coroutine(function *() { | |
yield Movie.query().insertWithRelated([{ | |
name: 'The terminator', | |
actors: [{ | |
"#id": 'arnold', | |
firstName: 'Arnold', | |
lastName: 'Schwarzenegger', | |
parent: { | |
firstName: 'Gustav', | |
lastName: 'Schwarzenegger' | |
} | |
}, { | |
firstName: 'Michael', | |
lastName: 'Biehn' | |
}], | |
reviews: [{ | |
title: 'Great movie', | |
stars: 5, | |
text: 'Awesome', | |
reviewer: { | |
firstName: 'Some', | |
lastName: 'Random-Dude' | |
} | |
}] | |
}, { | |
name: 'Terminator 2: Judgment Day', | |
actors: [{ | |
"#ref": 'arnold' | |
}] | |
}, { | |
name: 'Predator', | |
actors: [{ | |
"#ref": 'arnold' | |
}] | |
}]); | |
let reviews = yield Review | |
.query() | |
.eager('reviewer'); | |
console.log(JSON.stringify(reviews, null, 2)); | |
}); | |
// Run the whole thing. | |
createSchema() | |
.then(runQueries) | |
.finally(() => knex.destroy()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment