This is similar to the foreign key relationships we make in traditional SQL databases. Here, we link two or more tables using the index. We can also query the table using functions provided by RethinkDB to perform various joins (inner, outer, and so on):
As shown in the preceding diagram, we have two tables with multiple documents in them. The Authors table will just contain documents related to authors, say name, location, and (obviously) a primary key.
Demerits of document linking
The following demerits are:
- There are no foreign key constraints, so linking of data will be complicated
- In the case of an update in one table, it won't automatically update the data in another table
Here is a list of JOIN commands provided by RethinkDB:
- eq_Join
- innerJoin
- outerJoin
- Zip
Before looking at these, let's populate some data in two tables. We have authors and chapters in the books database.
We will add author details in the authors table:
r.db('books').table('authors').insert({name : "Shahid", location : "Mumbai"})
We will be adding chapter details in the chapters table:
r.db('books').table('chapters').insert({
author_id : "521b92b1-0d83-483d-a374-b94a400cf699",
chapterName : "Chapter 1"
})
r.db('books').table('chapters').insert({
author_id : "521b92b1-0d83-483d-a374-b94a400cf699",
chapterName : "Chapter 2"
})
Performing eq_Join
Here we are joining the chapters table with the authors table and mentioning which field we have mapped to the ID, that is, author_id
:
r.db('books').table('chapters').eqJoin("author_id",r.db('books').table('authors'))
This will return the following:
[
{
"left":{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 1",
"id":"f0b5b2f7-1f82-41ef-a945-f5fa8259dd53"
},
"right":{
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
}
},
{
"left":{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 2",
"id":"f58826d4-e259-4ae4-91e4-d2e3db2d9ad3"
},
"right":{
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
}
}
]
The left and right keys supposedly represent the tables on the left side and the right side of the query. If you map the keys and values with the ReQL query, you can easily understand.
However, this is not how we really want our data. We want processed, result-oriented data, and to do that, we need to use the zip()
command. It basically removes all metadata information from the result and gives you only the documents of tables:
r.db('books').table('chapters').eqJoin("author_id",r.db('books').table('authors')).zip()
This returns the following:
[
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 1",
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
},
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 2",
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
}
]
Performing inner joins
An inner join, as we all know, equates two tables by comparing each row. It is very similar to working with EQJOIN, except that it compares each document in the table against the target table, while in EQJOIN, we specify which key to compare for.
Here is a simple query to perform an inner join:
r.db('books').table('chapters').innerJoin(r.db('books').table('authors'),function(chapters,authors) {
return chapters
}).zip()
This function takes the target table as a parameter and the callback function, which contains data of both the tables in the callback argument. If you notice, for understanding, I've named the callback parameters the same as the table name. You can perform a lot of other operations such as comparison, or filtering inside the callback function and then returning the result. Since it's a JOIN, in both the variables, data will be similar-except with different table ID's.
Here is the result for the same:
[
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 1",
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
},
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 2",
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
}
]
If you observe, the result set is pretty much the same as EQJOIN (the eq_Join()
function), except that it provides you the result of each document under the callback function. This makes it really slow, and the RethinkDB team does not recommend it for use in production.
Performing outer joins
Outer join union the result of left join and right join and returns it to the client. So, basically, the result test from both the tables will be combined and returned. Here is a sample query.
r.db('books').table('chapters').outerJoin(r.db('books').table('authors'),function(chapters,authors) {
return authors
}).zip()
This will combine each document of chapters
with each document of authors
and return the result. Again, we can access each document of the query here under the callback.
It shall return the following:
[
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 1",
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
},
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 2",
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
}
]
In order to check it is working, let's just create one more author in the authors table and not create any chapter document entry for it:
r.db('books').table('authors').insert({name : "RandomGuy", location : "California"})
Upon running the outer join query again, here is the result:
[
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 1",
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
},
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 2",
"id":"521b92b1-0d83-483d-a374-b94a400cf699",
"location":"Mumbai",
"name":"Shahid"
},
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 1",
"id":"78acabb5-a5b8-434b-acb1-52507b71831d",
"location":"California",
"name":"RandomGuy"
},
{
"author_id":"521b92b1-0d83-483d-a374-b94a400cf699",
"chapterName":"Chapter 2",
"id":"78acabb5-a5b8-434b-acb1-52507b71831d",
"location":"California",
"name":"RandomGuy"
}
]
Hence we get all of the result-the union of each document of the table present in the left table (that is, authors) with each document present in the right table (that is, chapters).
Zip
This function performs the merging of left fields with right fields with a JOIN
operation into a single dataset.