!CHAPTER Joins So far we have only dealt with one collection (*users*) at a time. We also have a collection *relations* that stores relationships between users. We will now use this extra collection to create a result from two collections. First of all, we'll query a few users together with their friends' ids. For that, we'll use all *relations* that have a value of *friend* in their *type* attribute. Relationships are established by using the *from* and *to* attributes in the *relations* collection, which point to the *id* values in the *users* collection. !SUBSECTION Join tuples We'll start with a SQL-ish result set and return each tuple (user name, friend id) separately. The AQL query to generate such result is: ```js FOR u IN users FILTER u.active == true LIMIT 0, 4 FOR f IN relations FILTER f.type == "friend" && f.from == u.id RETURN { "user" : u.name, "friendId" : f.to } [ { "user" : "Abigail", "friendId" : 108 }, { "user" : "Abigail", "friendId" : 102 }, { "user" : "Abigail", "friendId" : 106 }, { "user" : "Fred", "friendId" : 209 }, { "user" : "Mary", "friendId" : 207 }, { "user" : "Mary", "friendId" : 104 }, { "user" : "Mariah", "friendId" : 203 }, { "user" : "Mariah", "friendId" : 205 } ] ``` !SUBSECTION Horizontal lists Note that in the above result, a user might be returned multiple times. This is the SQL way of returning data. If this is not desired, the friends' ids of each user can be returned in a horizontal list. This will return each user at most once. The AQL query for doing so is: ```js FOR u IN users FILTER u.active == true LIMIT 0, 4 RETURN { "user" : u.name, "friendIds" : ( FOR f IN relations FILTER f.from == u.id && f.type == "friend" RETURN f.to ) } [ { "user" : "Abigail", "friendIds" : [ 108, 102, 106 ] }, { "user" : "Fred", "friendIds" : [ 209 ] }, { "user" : "Mary", "friendIds" : [ 207, 104 ] }, { "user" : "Mariah", "friendIds" : [ 203, 205 ] } ] ``` In this query we are still iterating over the users in the *users* collection and for each matching user we are executing a sub-query to create the matching list of related users. !SUBSECTION Self joins To not only return friend ids but also the names of friends, we could "join" the *users* collection once more (something like a "self join"): ```js FOR u IN users FILTER u.active == true LIMIT 0, 4 RETURN { "user" : u.name, "friendIds" : ( FOR f IN relations FILTER f.from == u.id && f.type == "friend" FOR u2 IN users FILTER f.to == u2.id RETURN u2.name ) } [ { "user" : "Abigail", "friendIds" : [ "Jim", "Jacob", "Daniel" ] }, { "user" : "Fred", "friendIds" : [ "Mariah" ] }, { "user" : "Mary", "friendIds" : [ "Isabella", "Michael" ] }, { "user" : "Mariah", "friendIds" : [ "Madison", "Eva" ] } ] ```