First $lookup
1db.ns_material_categories.aggregate( 2 [ 3 { 4 $lookup: { 5 from: "ns_material_category_groups", 6 localField: "group_code", 7 foreignField: "code", 8 as: "properties" 9 } 10 },
The $lookup
here is the most basic form, which do a left join by gluing group_code
and code
.
Second $lookup
The next one is a generalization of the first $lookup
.
11 { 12 $unwind: "$properties" 13 }, 14 { 15 $lookup: { 16 let: { code: "$code" }, 17 from: "ns_materials", 18 pipeline: [ 19 { 20 $match: { 21 $expr: { 22 $and: [ 23 {$eq: ["$category_code", "$$code"]}, 24 {$eq: ["$is_dummy", "Y"]} 25 ] 26 } 27 } 28 }, 29 { 30 $project: { 31 _id: 0, 32 manu_code: 1, 33 model_code: 1, 34 name: 1 35 } 36 } 37 ], 38 as: "suppliers" 39 } 40 } 41 ] 42)
This is somewhat more complicated, but the pipeline
makes it much more flexible than the basic form.
The from-let-pipeline-as
lookup
from-let-pipeline-as
lookupFor look up we have either
from-localField-foreignField-as
from-let-pipeline-as
There is nopipeline
when eitherlocalField
orforeignField
exists.
We try to break down to explain the more advanced $lookup
, we start form line 16 of the code blocks above.
-
In
let
we have${code: "$code"}
, the keycode
is the variable name for temp storage, the"$code"
is the field path of an object from the upstream collection in the pipeline. -
We store all desired variable in the
let
stage. In this example, we will unwrap and utilize the value by writing"$$code"
. -
We use
$expr
to instantiate any comparison. -
The basic
$lookup
can just doselect a.* from A left join B b on b.a_id = a.id
-
whereas the advanced
$lookup
can doselect b.sth1, b.sth2, a.* from A a left join B b on b.id = b_id and ... and ... and ...
due to the field
pipeline
.
Using Javascript in $lookup with Pipeline!
pipeline: [ { $lookup: { from: "ns_generic_form_templates", let: { code: "$code" }, pipeline: [ { $project: { subtypes: 1 } }, { $addFields: { formAnalysis: { $function: { body: function (code, subtypes, formId) { if (!subtypes) { return null } else { const hasForm = subtypes.indexOf(code) > -1; return { category_code: code, hasForm, formOid: formId } } }, args: ["$$code", "$subtypes", "$_id"], lang: 'js' } } } }, { $project: { subtypes: 0 } } { $match: { "formAnalysis.hasForm": true } }, { $limit: 1 }, { $replaceRoot: { newRoot: "$formAnalysis" } }, { $set: { formOid: { $toString: "$formOid" } } }, ], as: "genericForm" } }, { $unwind: "$genericForm" } ]