Subcollection (Input Stage)

Description

The subcollection(...) input stage makes it easy to perform parent-child joins using the built-in __name__ field.

Additional stages can be chained onto the subcollection(...) stage to perform filtering or aggregation over the nested documents. Note that any field references used in subsequent stages refer to the documents from the nested collection, not the parent document. To refer to fields in the parent scope, first use the let stage to define variables, then reference those variables in the local scope.

Syntax

Node.js

  db 
 . 
 pipeline 
 () 
  
 . 
 collection 
 ( 
 "/restaurants" 
 ) 
  
 . 
 add_fields 
 ( 
 subcollection 
 ( 
 "reviews" 
 ) 
  
 . 
 aggregate 
 ( 
 average 
 ( 
 "rating" 
 ). 
 as 
 ( 
 "avg_rating" 
 )) 
  
 . 
 toScalarExpression 
 () 
  
 . 
 as 
 ( 
 "avg_rating" 
 )) 
 

Behavior

The subcollection(...) stage must be used within the context of a sub-pipeline. It uses the __name__ (the document reference) of the current document in the parent scope to determine which sub-collection to fetch. For example, if the parent document is /restaurants/pizza-place , then subcollection("reviews") returns all documents from the /restaurants/pizza-place/reviews collection.

If the document reference has been renamed, or it is not possible to define a field with __name__ then manually writing the join like:

Node.js

  db 
 . 
 pipeline 
 () 
  
 . 
 collection 
 ( 
 "/restaurants" 
 ) 
  
 . 
 let 
 ( 
 field 
 ( 
 "__name__" 
 ). 
 as 
 ( 
 "restaurant_name" 
 )) 
  
 . 
 add_fields 
 ( 
 db 
 . 
 pipeline 
 () 
  
 . 
 collectionGroup 
 ( 
 "reviews" 
 ) 
  
 . 
 where 
 ( 
 field 
 ( 
 "__name__" 
 ). 
 parent 
 (). 
 equals 
 ( 
 variable 
 ( 
 "restaurant_name" 
 ))) 
  
 . 
 aggregate 
 ( 
 average 
 ( 
 "rating" 
 ). 
 as 
 ( 
 "avg_rating" 
 )) 
  
 . 
 toScalarExpression 
 () 
  
 . 
 as 
 ( 
 "avg_rating" 
 )) 
 

is still possible as fundamentally this stage is just syntactic sugar over this more complex join format.

Example

For the following documents:

Node.js

  const 
  
 restaurant1 
  
 = 
  
 db 
 . 
 collection 
 ( 
 "restaurants" 
 ). 
 document 
 ( 
 "pizza-place" 
 ); 
 const 
  
 restaurant2 
  
 = 
  
 db 
 . 
 collection 
 ( 
 "restaurants" 
 ). 
 document 
 ( 
 "urban-bite" 
 ); 
 const 
  
 restaurant3 
  
 = 
  
 db 
 . 
 collection 
 ( 
 "restaurants" 
 ). 
 document 
 ( 
 "nacho-house" 
 ); 
 await 
  
 restaurant1 
 . 
 create 
 ({ 
  
 name 
 : 
  
 "Pizza Place" 
  
 }); 
 await 
  
 restaurant2 
 . 
 create 
 ({ 
  
 name 
 : 
  
 "Urban Bite" 
  
 }); 
 await 
  
 restaurant3 
 . 
 create 
 ({ 
  
 name 
 : 
  
 "Nacho House" 
  
 }); 
 await 
  
 restaurant1 
 . 
 collection 
 ( 
 "reviews" 
 ). 
 doc 
 ( 
 "1" 
 ). 
 create 
 ({ 
  
 rating 
 : 
  
 5 
  
 }); 
 await 
  
 restaurant1 
 . 
 collection 
 ( 
 "reviews" 
 ). 
 doc 
 ( 
 "1" 
 ). 
 create 
 ({ 
  
 rating 
 : 
  
 2 
  
 }); 
 await 
  
 restaurant2 
 . 
 collection 
 ( 
 "reviews" 
 ). 
 doc 
 ( 
 "1" 
 ). 
 create 
 ({ 
  
 rating 
 : 
  
 3 
  
 }); 
 await 
  
 restaurant2 
 . 
 collection 
 ( 
 "reviews" 
 ). 
 doc 
 ( 
 "1" 
 ). 
 create 
 ({ 
  
 rating 
 : 
  
 4 
  
 }); 
 await 
  
 restaurant2 
 . 
 collection 
 ( 
 "reviews" 
 ). 
 doc 
 ( 
 "1" 
 ). 
 create 
 ({ 
  
 rating 
 : 
  
 5 
  
 }); 
 

The following query retrieves each restaurant and summarizes its reviews in a new review_summary field:

Node.js

  const 
  
 results 
  
 = 
  
 await 
  
 db 
 . 
 pipeline 
 () 
  
 . 
 collectionGroup 
 ( 
 "restaurants" 
 ) 
  
 . 
 add_fields 
 ( 
 subcollection 
 ( 
 "reviews" 
 ) 
  
 . 
 aggregate 
 ( 
  
 countAll 
 (). 
 as 
 ( 
 "review_count" 
 ), 
  
 average 
 ( 
 "rating" 
 ). 
 as 
 ( 
 "avg_rating" 
 )) 
  
 . 
 asScalarExpression 
 () 
  
 . 
 as 
 ( 
 "review_summary" 
 )) 
  
 . 
 execute 
 (); 
 

and produces the following results:

  { 
  
 name 
 : 
  
 "Pizza Place" 
 , 
  
 review_summary 
 : 
  
 { 
  
 review_count 
 : 
  
 2 
 , 
  
 avg_rating 
 : 
  
 3.5 
  
 } 
  
 }, 
 { 
  
 name 
 : 
  
 "Urban Bite" 
 , 
  
 review_summary 
 : 
  
 { 
  
 review_count 
 : 
  
 3 
 , 
  
 avg_rating 
 : 
  
 4.0 
  
 } 
  
 }, 
 { 
  
 name 
 : 
  
 "Nacho House" 
 , 
  
 review_summary 
 : 
  
 { 
  
 review_count 
 : 
  
 0 
 , 
  
 avg_rating 
 : 
  
 null 
  
 } 
  
 }, 
 
Create a Mobile Website
View Site in Mobile | Classic
Share by: