Skip to content

Commit 84db62b

Browse files
committed
Improved lookup, changed $set for $addFields
1 parent 2d61ea5 commit 84db62b

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

docs/60-lookups/lookups.mdx

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,77 @@
11
# Lookupups AKA Left Outer Join
22

3+
Using Documents we usually model 1:1, 1:many relationships embedding documents inside other documents, even using arrays for that. For instance an Author can have many aliases, and they live inside an array in the `authors` collection.
4+
5+
But other times we need to use references to those documents instead of embedding them. For instance an author has an array of the books she has written, but instead of moving the book documents inside an array inside author (which will be tricky for books with multiple authors) we embed the books `_id` instead.
6+
7+
So how can we get the authors and all the books she has written, embedded in the array? Using `$lookup`, that will do a Left Outer Join and return author docs containing book docs inside.
8+
9+
💻 Run this aggregation and look at the results:
10+
11+
```js
12+
db.authors.aggregate([
13+
{$lookup: {
14+
from: "books",
15+
localField: "books",
16+
foreignField: "_id",
17+
as: "booksWritten"
18+
}
19+
},
20+
{$project: {vectorizedSynopsis: 0, _id: 0}}
21+
])
22+
```
23+
24+
The syntax for this version of `$lookup` is:
25+
26+
```js
27+
{
28+
$lookup:
29+
{
30+
from: <collection to join>,
31+
localField: <field from the input documents>,
32+
foreignField: <field from the documents of the "from" collection>,
33+
as: <output array field>
34+
}
35+
}
36+
```
37+
38+
## Lookups from a previous stage
39+
40+
We can do a $lookup on the result of another pipeline, not only joining with a collection. For instance, we want to remove some noise from the books before joining, so we use `$project` to exclude a couple arrays.
41+
342
```js
443
db.authors.aggregate([
5-
{ $unwind : "$books" },
644
{$lookup: {
745
from: "books",
846
localField: "books",
947
foreignField: "_id",
48+
pipeline: [
49+
{$project: {title: 1, synopsis: 1}}
50+
],
1051
as: "booksWritten"
1152
}
1253
}
1354
])
1455
```
1556

57+
The nice part is that we can extract that pipeline and test it / tweak it.
58+
1659
```js
60+
let booksFrom1996 = [
61+
{$match: {year: 1996}},
62+
{$project: {title: 1, synopsis: 1}},
63+
]
64+
1765
db.authors.aggregate([
1866
{$lookup: {
1967
from: "books",
2068
localField: "books",
2169
foreignField: "_id",
70+
pipeline:
71+
booksFrom1996,
2272
as: "booksWritten"
2373
}
24-
},
25-
{$project: {vectorizedSynopsis: 0, _id: 0}}
74+
}
2675
])
27-
```
76+
```
77+

docs/70-modifying-results/adding-fields.mdx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Adding new fields to results
22

3-
We want to estimate the reading time for a book. But we don't have that field stored in our data.
3+
## $addFields
4+
5+
We want to estimate the reading time for a book. But we don't have that field stored in our data. We can use `$addFields` for this. If the field exists, it'll get updated, if not, it's added.
46

57
```js
68
db.books.aggregate([
@@ -9,7 +11,7 @@ db.books.aggregate([
911
pages: 1,
1012
}
1113
},
12-
{$set: {readingTimeHours: {$divide: [{$multiply: ["$pages", 2]}, 60]}}},
14+
{$addFields: {readingTimeHours: {$divide: [{$multiply: ["$pages", 2]}, 60]}}},
1315
])
1416
```
1517

@@ -29,7 +31,7 @@ db.books.aggregate([
2931

3032
},
3133

32-
{$set: {notes: "PLACEHOLDER"}}
34+
{$addFields: {notes: "PLACEHOLDER"}}
3335
])
3436
```
3537

0 commit comments

Comments
 (0)