Skip to content

Commit 69dcf4e

Browse files
committed
Added a lookup section
1 parent 0a77784 commit 69dcf4e

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed
File renamed without changes.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# 🦸‍♂️ Advanced lookups
2+
3+
:::info
4+
Extra activity, do it if you have extra time or are following at home, won't be covered during the hands-on Lab
5+
:::
6+
7+
We get this request: Write a `$lookup` to get `name` and `bio` from author's information inside each book document. To get this done, we need to review several things:
8+
9+
- each book can have several authors. This many to many relationship (as an author can also write many books) is modelled using two different arrays: a `books` array in the `authors` collection and an `authors` array in the `books` collection.
10+
- so we'll need to get a separate document for each book that has more than one author. If a book has three authors we'll use `$unwind` to get three documents with the same data except for the author, that will be each of the three authors.
11+
12+
You can try this with this Aggregation Pipeline:
13+
14+
```js
15+
db.books.aggregate([
16+
// as a book can have many authors, we get one doc per book's author
17+
{$unwind: "$authors"},
18+
// remove some noisy fields
19+
{$project: {vectorizedSynopsis: 0, attributes: 0, reviews: 0}}
20+
])
21+
```
22+
- now, we need to get the authors'information. For that, we'll use `$lookup`, linking the `_id` in the `authors` collection with the `_id` we have in each book's `authors` array. But as we can see here, these have a different type: the ones inside our array are Strings, while the `author` collection `_id` are `ObjectId`.
23+
24+
```js
25+
authors: {
26+
_id: '64cc2db4830ba29148da64a2',
27+
name: 'Timothy Findley'
28+
},
29+
```
30+
31+
So we need to convert from `String` into `ObjectId`. We can do that using `$toObjectId`. This will add a new field `authorId` converting it into `ObjectId`:
32+
33+
```js
34+
db.books.aggregate([
35+
// as a book can have many authors, we get one doc per book's author
36+
{$unwind: "$authors"},
37+
// convert it to an objectId
38+
{"$set":{"authorId":{"$toObjectId":"$authors._id"}}},
39+
// remove some noisy fields
40+
{$project: {vectorizedSynopsis: 0, attributes: 0, reviews: 0}}
41+
])
42+
```
43+
44+
- now we're ready to do the `$lookup`: we want all documents from `authors` that have the same `_id` as the `authorId` we just created. We use a `pipeline` to get just `authors` `name` and `bio`.
45+
46+
```js
47+
db.books.aggregate([
48+
// as a book can have many authors, we get one doc per book's author
49+
{$unwind: "$authors"},
50+
// convert it to an objectId
51+
{"$set":{"authorId":{"$toObjectId":"$authors._id"}}},
52+
{$lookup: {
53+
from: "authors",
54+
localField: "authorId",
55+
foreignField: "_id",
56+
pipeline: [
57+
{$project: {name: 1, bio: 1}},
58+
],
59+
as: "bookAuthorDetails"
60+
}
61+
},
62+
// remove some noisy fields
63+
{$project: {vectorizedSynopsis: 0, attributes: 0, reviews: 0}}
64+
])
65+
```
66+
67+

docs/80-modifying-results/missing-data.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Missing Data
22

3+
Sometimes we're missing a field we're looking for (it's not there, as documents in a collection can be polymorphic, so this field is `null`). For these cases we can check if something is there using `$ifNull` and add a default value in that case.
34

45
```js
56
let getAuthorsWithBooks = {

0 commit comments

Comments
 (0)