Specify the SQL Table and Its Unique Key
We'll add a couple of properties to the GraphQLObjectType
definition on User
. Our users data lives in the accounts
table, so we'll set the sqlTable
property to 'accounts'
.
We also need a unique identifier so it's unambiguous which objects are distinct entities and which were duplicated due to a join. Our accounts
table has a primary key, the 'id'
, so we'll set that as the uniqueKey
property. The uniqueKey
does not need to have any constraints in the actual database. It's up to you to make sure no duplicate values exist in whichever column you indicate as being unique.
const User = new GraphQLObjectType({
name: 'User',
sqlTable: 'accounts', // the SQL table for this object type is called "accounts"
uniqueKey: 'id', // id is different for every row
fields: () => ({ /*...*/ })
})
Table Name Details
If your table is on a SQL schema that is not the default, e.g. public
, you can specify it in sqlTable
with a dot separator. You must escape any characters that need to be escaped for your particular SQL database. For example, in SQLite3 or PostgreSQL, names that include characters other than a-z, #, and $ (for example capital letters) must be wrapped in double quotes. In MySQL/MariaDB, you would use backticks.
const User = new GraphQLObjectType({
name: 'User',
sqlTable: 'public."Accounts"', // the SQL table is on the schema "public" called "Accounts"
uniqueKey: 'id',
fields: () => ({ /*...*/ })
})
The sqlTable
can generalize to any table expression. Instead of a physical table, it could be a VIEW or a derived table.
const User = new GraphQLObjectType({
name: 'User',
sqlTable: '(SELECT * FROM accounts WHERE active = 1)', // this can be an expression that generates a TABLE
uniqueKey: 'id',
fields: () => ({ /*...*/ })
})
This can be a useful technique if you data isn't actually modelled like Join Monster expects. Placing VIEWs on top of your SQL tables is a good way to achieve logical data independence.
The sqlTable
can also be a function, i.e. a thunk.
Composite Keys
If no single column in your table is unique, that's okay. Perhaps you have a composite key, where the combined value of multiple column is unique for each row.
generation | first_name | last_name |
---|---|---|
1 | erlich | bachman |
1 | andrew | bachman |
2 | erlich | bachman |
2 | matt | bachman |
1 | matt | daemon |
Just make uniqueKey
an array of string instead of a string. Join Monster will use the SQL ||
operator or the CONCAT
function to concatenate the values of those columns and identify the row based on the combination.
const User = new GraphQLObjectType({
name: 'User',
sqlTable: 'accounts',
uniqueKey: [ 'generation', 'first_name', 'last_name' ],
fields: () => ({ /*...*/ })
})