The $group Stage
{
$group:
{
_id: <expression>, // Group key
<field1>: { <accumulator1> : <expression1> },
...
}
}
Accumulator Stages with $project
근데 이를 간단하게 처리할 수 있다! -> Accumulator 연산자 + $project
The $unwind Stage
{ $unwind: <field path> }
{
$unwind:
{
path: <field path>,
includeArrayIndex: <string>,
preserveNullAndEmptyArrays: <boolean>
}
}
-> includeArrayIndex : 배열 요소의 순번을 표시한다.
-> preserveNullAndEmptyArrays : 지정된 field path에 원소가 없거나 null 이어도 출력하는지 여부 ( 기본 값 : false)
The $lookup Stage
--> LEFT OUTER JOIN
LEFT OUTER JOIN은 왼쪽 테이블의 것은 조건에 부합하지 않더라도 모두 결합되어야 한다는 의미이다.
즉, FROM 첫번째 테이블 LEFT OUTER JOIN 두번째 테이블이라면 첫번째 테이블의 것은 모두 출력되어야 한다.
참고 : https://qqplot.github.io/database/2021/09/15/left_outer_join.html
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
$graphLookup Introduction
{
$graphLookup: {
from: <collection>,
startWith: <expression>,
connectFromField: <string>,
connectToField: <string>,
as: <string>,
maxDepth: <number>,
depthField: <string>,
restrictSearchWithMatch: <document>
}
}
from : $graphLookup 대상 컬렉션
컬렉션 from은 작업에 사용된 다른 컬렉션과 동일한 데이터베이스에 있어야 하며, MongoDB 5.1부터 매개 from변수에 지정된 컬렉션을 샤딩할 수 있다.
startWith : 재귀 검색을 시작할 값을 지정하는 식
connectFromField : 재귀 호출하여 일치하는 값이 있는 from 컬렉션의 문서 connectToField 와 일치시키는 필드 (.. 모르겟음..뭔말인지..)
connectToField : connectFromField 에 지정된 필드와 일치 시킬 다른 문서의 필드
as : 각 출력 문서에 추가된 배열 필드의 이름
maxDepth : 최대 재귀 깊이를 지정하는 음이 아닌 정수 (선택요소)
depthField : 검색 경로에서 순회된 각 문서에 추가할 필드의 이름
이 필드의 값은 NumberLong 로 표시되는 문서의 재귀 깊이.
restrictSearchWithMatch : 재귀 검색을 위한 추가 조건을 지정하는 문서
db.employees.aggregate( [
{
$graphLookup: {
from: "employees",
startWith: "$reportsTo",
connectFromField: "reportsTo",
connectToField: "name",
as: "reportingHierarchy"
}
}
] )
...뭥미 어려움...!
practice
var pipeline = [
{
$match: {
"awards.text": /Won \d{1,2} Oscars?/
}
},
{
$group: {
_id: null,
highest_rating: { $max: "$imdb.rating" },
lowest_rating: { $min: "$imdb.rating" },
average_rating: { $avg: "$imdb.rating" },
deviation: { $stdDevSamp: "$imdb.rating" }
}
}
]
var pipeline = [
{
$match: {
languages: "English"
}
},
{
$project: { _id: 0, cast: 1, "imdb.rating": 1 }
},
{
$unwind: "$cast"
},
{
$group: {
_id: "$cast",
numFilms: { $sum: 1 },
average: { $avg: "$imdb.rating" }
}
},
{
$project: {
numFilms: 1,
average: {
$divide: [{ $trunc: { $multiply: ["$average", 10] } }, 10]
}
}
},
{
$sort: { numFilms: -1 }
},
{
$limit: 1
}
]
var pipeline = [
{
$match: {
airplane: /747|380/
}
},
{
$lookup: {
from: "air_alliances",
foreignField: "airlines",
localField: "airline.name",
as: "alliance"
}
},
{
$unwind: "$alliance"
},
{
$group: {
_id: "$alliance.name",
count: { $sum: 1 }
}
},
{
$sort: { count: -1 }
}
]
db.air_routes.aggregate(pipeline)
var pipeline = [
{
$match: { name: "OneWorld" }
}, {
$graphLookup: {
startWith: "$airlines",
from: "air_airlines",
connectFromField: "name",
connectToField: "name",
as: "airlines",
maxDepth: 0,
restrictSearchWithMatch: {
country: { $in: ["Germany", "Spain", "Canada"] }
}
}
}, {
$graphLookup: {
startWith: "$airlines.base",
from: "air_routes",
connectFromField: "dst_airport",
connectToField: "src_airport",
as: "connections",
maxDepth: 1
}
}, {
$project: {
validAirlines: "$airlines.name",
"connections.dst_airport": 1,
"connections.airline.name": 1
}
},
{ $unwind: "$connections" },
{
$project: {
isValid: { $in: ["$connections.airline.name", "$validAirlines"] },
"connections.dst_airport": 1
}
},
{ $match: { isValid: true } },
{ $group: { _id: "$connections.dst_airport" } },
{ $sort: { _id: 1 } }
]