I'm writing an application that contains an overall data model with some obvious relations. I started writing the application using MongoDB (what I'm familiar with), but decided to try and transition over to Postgres since again, my data has tons of foreign keys. For simplicity, let's consider the following models:
class GameBase {
id: string
entryIds: string[]
submissionIds: string[]
}
class EntryBase {
id: string
description: string
gameId: string
userId: string // id of user who supplied entry
submissionIds: string[] // submissions where entry is covered
}
class SubmissionBase {
id: string
url: string
gameId: string
userId: string // id of user who submitted
entryIds: string[] // entries covered by submission
}
Now I understand if I use a tool like TypeOrm, I could retrieve these relations with something like:
const games = await gameRepository
.find({ relations: ["entryIds", "submissionIds"] });
(Or something to that effect)
But I'm not really sure how that relates to GraphQL. What I've been doing up until now is adding @ResolveField
inside my Resolvers and writing something like
// in resolver
@ResolveField(() => [SubmissionBase], { nullable: true })
submissions(@Parent() game: GameBase) {
return this.submissionService.getManySubmissions(game.submissionIds)
}
// in service
async getManySubmissions(submissionIds: string[]): Promise<SubmissionBase[]> {
if (!submissionIds) return []
return await this.submissionRepository.find({
where: {
id: { $in: submissionIds },
},
})
}
So this makes sense to me and has been working great. I just keep having a nagging feeling like I need to switch to a relational database. From what you all can tell, is that nagging feeling rooted in truth? For example, if the same .find
method you see in my service above was instead backed by Postgres instead of MongoDB, and the appropriate foreign key relationship was established, would I see speed improvements? Although submissionIds
is not a true foreign key (bc Mongo), it still acts as one in this setup. I guess I'm failing to see why MongoDB is a bad choice for relational data if you can use something like @ResolveField
to grab whatever you need.
Why would YOU recommend using MongoDB over Postgres or Postgres over MongoDB given this type of model setup?
From my understanding of GraphQL, you wouldn't be using foreign keys to reference another child/parent object somewhere else (at least not in the GraphQL schema). You would instead have the child object actually inside the parent object. For example, in
GameBase
, it would look something like this:This doesn't convert perfectly to a NoSql nor a Relationship database model because the graphQL schemas are independent of how you actually store the data. GraphQL schemas are excellent at representing relational data, but it does not imply that a relational database would be better fitting.
The choice between a relational database and a NoSQL database should be made based off of a few things (off the top of my head):
GetAllEntriesForSpecificSubmissions
orGetGameIdsByEntries
. For each one of these queries in a NoSQL world, chances are, you would just need to duplicate the data to optimize for these queries. In a relational database world, you could probably just get nifty with your query and not need to duplicate anything.I am sure there is even more to consider, but these things come to mind for me.
Would I recommend one over the other personally? Lets see:
Yup. NoSQL. But only if you allow yourself to do it right. I see too often people trying to join across NoSQL databases/collections to get data. Nope. Just duplicate it (most of the time).