์ง๊ณ ํ์ดํ๋ผ์ธ ์ต์ ํ
์ด ํ์ด์ง์ ๋ด์ฉ
์ง๊ณ ํ์ดํ๋ผ์ธ ์์ ์๋ ์ฑ๋ฅ ํฅ์์ ์ํด ํ์ดํ๋ผ์ธ์ ์ฌ๊ตฌ์ฑํ๋ ์ต์ ํ ๋จ๊ณ๊ฐ ์์ต๋๋ค.
์ตํฐ๋ง์ด์ ๊ฐ ํน์ ์ง๊ณ ํ์ดํ๋ผ์ธ์ ์ด๋ป๊ฒ ๋ณํํ๋์ง ํ์ธํ๋ ค๋ฉด explain
์ต์
์ db.collection.aggregate()
๋ฉ์๋์ ํฌํจํฉ๋๋ค.
์ต์ ํ๋ ๋ฆด๋ฆฌ์ค ๊ฐ์ ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค.
์ต์ ํ ๋จ๊ณ์์ ์ํ๋๋ ์ง๊ณ ํ์ดํ๋ผ์ธ ์ต์ ํ์ ๋ํด ์์๋ณด๋ ๊ฒ ์ธ์๋ ์ธ๋ฑ์ค ๋ฐ ๋ฌธ์ ํํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ง๊ณ ํ์ดํ๋ผ์ธ ์ฑ๋ฅ์ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ๋ ํ์ธํ ์ ์์ต๋๋ค.
MongoDB Atlas์์ ํธ์คํ ๋๋ ๋ฐฐํฌ์ ๋ํด UI์์ ์ง๊ณ ํ์ดํ๋ผ์ธ์ ์คํํ ์ ์์ต๋๋ค.
ํ๋ก์ ์ ์ต์ ํ
์ง๊ณ ํ์ดํ๋ผ์ธ์ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ ์ํด ๋ฌธ์ ํ๋์ ํ์ ์งํฉ๋ง ํ์ํ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ํ์ดํ๋ผ์ธ์ ํด๋น ํ๋๋ง ์ฌ์ฉํ๋ฏ๋ก ํ์ดํ๋ผ์ธ์ ํต๊ณผํ๋ ๋ฐ์ดํฐ ์์ด ์ค์ด๋ญ๋๋ค.
$project
๋จ๊ณ ๋ฐฐ์น
$project
๋จ๊ณ๋ฅผ ์ฌ์ฉํ ๋๋ ์ผ๋ฐ์ ์ผ๋ก ํ์ดํ๋ผ์ธ์ ๋ง์ง๋ง ๋จ๊ณ์ฌ์ผ ํ๋ฉฐ, ์ด๋ ํด๋ผ์ด์ธํธ์ ๋ฐํํ ํ๋๋ฅผ ์ง์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
ํ์ดํ๋ผ์ธ์ ์์ ๋๋ ์ค๊ฐ์ $project
๋จ๊ณ๋ฅผ ์ฌ์ฉํ์ฌ ํ์ ํ์ดํ๋ผ์ธ ๋จ๊ณ๋ก ์ ๋ฌ๋๋ ํ๋ ์๋ฅผ ์ค์ด๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ด ์ต์ ํ๋ฅผ ์๋์ผ๋ก ์ํํ๋ฏ๋ก ์ฑ๋ฅ์ด ํฅ์๋์ง ์์ ์ ์์ต๋๋ค.
ํ์ดํ๋ผ์ธ ์ํ์ค ์ต์ ํ
($project
๋๋ $unset
๋๋ $addFields
๋๋ $set
) + ์ํ์ค $match
์ต์ ํ
ํ๋ก์ ์
๋จ๊ณ($addFields
, $project
, $set
, $unset
) ๋ค์ $match
๋จ๊ณ๊ฐ ํฌํจ๋ ์ง๊ณ ํ์ดํ๋ผ์ธ์ ๊ฒฝ์ฐ, MongoDB๋ ํ๋ก์ ์
๋จ๊ณ์์ ๊ณ์ฐ๋ ๊ฐ์ ํ์๋ก ํ์ง ์๋ $match
๋จ๊ณ์ ํํฐ๋ฅผ ํ๋ก์ ์
์ ์ ์๋ก์ด $match
๋จ๊ณ๋ก ์ด๋ํฉ๋๋ค.
์ง๊ณ ํ์ดํ๋ผ์ธ์ ์ฌ๋ฌ ๊ฐ์ ํ๋ก์ ์
๋๋ $match
๋จ๊ณ๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ, MongoDB๋ ๊ฐ $match
๋จ๊ณ์ ๋ํด ์ด ์ต์ ํ๋ฅผ ์ํํ์ฌ, ํํฐ๊ฐ ์์กดํ์ง ์๋ ๋ชจ๋ ํ๋ก์ ์
๋จ๊ณ ์์ผ๋ก ๊ฐ $match
ํํฐ๋ฅผ ์ด๋์ํต๋๋ค.
๋ค์ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋ ํ์ดํ๋ผ์ธ์ ์๊ฐํด ๋ณด์ธ์.
{ $addFields: { maxTime: { $max: "$times" }, minTime: { $min: "$times" } } }, { $project: { _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1, avgTime: { $avg: ["$maxTime", "$minTime"] } } }, { $match: { name: "Joe Schmoe", maxTime: { $lt: 20 }, minTime: { $gt: 5 }, avgTime: { $gt: 7 } } }
์ตํฐ๋ง์ด์ ๋ $match
๋จ๊ณ๋ฅผ 4๊ฐ์ ๊ฐ๋ณ ํํฐ( $match
์ฟผ๋ฆฌ ๋ฌธ์์ ๊ฐ ํค์ ๋ํด ํ๋์ฉ)๋ก ๋๋๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ตํฐ๋ง์ด์ ๋ ๊ฐ ํํฐ๋ฅผ ๊ฐ๋ฅํ ๋ง์ ํ๋ก์ ์
๋จ๊ณ ์์ผ๋ก ์ด๋์์ผ, ํ์์ ๋ฐ๋ผ ์๋ก์ด $match
๋จ๊ณ๋ฅผ ์์ฑํฉ๋๋ค.
์ด ์์์์ ์ตํฐ๋ง์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ ์ต์ ํ๋ ํ์ดํ๋ผ์ธ์ ์๋์ผ๋ก ์์ฑํฉ๋๋ค.
{ $match: { name: "Joe Schmoe" } }, { $addFields: { maxTime: { $max: "$times" }, minTime: { $min: "$times" } } }, { $match: { maxTime: { $lt: 20 }, minTime: { $gt: 5 } } }, { $project: { _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1, avgTime: { $avg: ["$maxTime", "$minTime"] } } }, { $match: { avgTime: { $gt: 7 } } }
์ฐธ๊ณ
์ต์ ํ๋ ํ์ดํ๋ผ์ธ์ ์๋์ผ๋ก ์คํํ๊ธฐ ์ํ ๊ฒ์ด ์๋๋๋ค. ์๋ณธ ํ์ดํ๋ผ์ธ๊ณผ ์ต์ ํ๋ ํ์ดํ๋ผ์ธ์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
๊ณํ ์ค๋ช ์์ ์ต์ ํ๋ ํ์ดํ๋ผ์ธ์ ํ์ธํ ์ ์์ต๋๋ค.
$match
ํํฐ { avgTime: { $gt: 7 } }
๋ avgTime
ํ๋๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด $project
๋จ๊ณ์ ์์กดํฉ๋๋ค. ์ด ํ์ดํ๋ผ์ธ์์ $project
๋จ๊ณ๋ ๋ง์ง๋ง ํ๋ก์ ์
๋จ๊ณ์ด๋ฏ๋ก avgTime
์ ๋ํ $match
ํํฐ๋ ์ด๋๋ ์ ์์ต๋๋ค.
maxTime
๋ฐ minTime
ํ๋๋ $addFields
๋จ๊ณ์์ ๊ณ์ฐ๋์ง๋ง $project
๋จ๊ณ์ ๋ํ ์ข
์์ฑ์ ์์ต๋๋ค. ์ตํฐ๋ง์ด์ ๋ ์ด๋ฌํ ํ๋๋ค์ ๋ํ ํํฐ๋ฅผ ์ํ ์๋ก์ด $match
๋จ๊ณ๋ฅผ ๋ง๋ค์๊ณ ์ด๋ฅผ $project
๋จ๊ณ ์์ ๋ฐฐ์นํ์ต๋๋ค.
$match
ํํฐ { name: "Joe Schmoe" }
๋ $project
๋๋ $addFields
๋จ๊ณ์์ ๊ณ์ฐ๋ ๊ฐ์ ์ฌ์ฉํ์ง ์์ผ๋ฏ๋ก, ์ด ํํฐ๋ ๋ ํ๋ก์ ์
๋จ๊ณ ์์ ์๋ก์ด $match
๋จ๊ณ๋ก ์ด๋๋์์ต๋๋ค.
์ต์ ํ ํ ํํฐ { name: "Joe Schmoe" }
๋ ํ์ดํ๋ผ์ธ ์์ ๋ถ๋ถ์ $match
๋จ๊ณ์ ์๊ฒ ๋ฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฒ์์ ์ปฌ๋ ์
์ ์ฟผ๋ฆฌํ ๋ ์ง๊ณ๊ฐ name
ํ๋์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ์ถ๊ฐ์ ์ธ ์ด์ ์ด ์์ต๋๋ค.
$sort
+ ์ํ์ค $match
์ต์ ํ
$sort
๋ค์ $match
๊ฐ ์๋ ์ํ์ค๊ฐ ์๋ ๊ฒฝ์ฐ, ์ ๋ ฌํ ๊ฐ์ฒด ์๋ฅผ ์ต์ํํ๊ธฐ ์ํด $match
๋ฅผ $sort
์์ผ๋ก ์ด๋ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ํ์ดํ๋ผ์ธ์ด ๋ค์๊ณผ ๊ฐ์ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋์ด ์๋ ๊ฒฝ์ฐ์
๋๋ค.
{ $sort: { age : -1 } }, { $match: { status: 'A' } }
์ต์ ํ ๋จ๊ณ์์ ์ตํฐ๋ง์ด์ ๋ ์ํ์ค๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณํํฉ๋๋ค.
{ $match: { status: 'A' } }, { $sort: { age : -1 } }
$redact
+ ์ํ์ค $match
์ต์ ํ
๊ฐ๋ฅํ ๊ฒฝ์ฐ ํ์ดํ๋ผ์ธ์ $redact
๋จ๊ณ ๋ฐ๋ก ๋ค์ $match
๋จ๊ณ๊ฐ ์๋ ๊ฒฝ์ฐ, ์ง๊ณ๋ ๋๋๋ก $redact
๋จ๊ณ ์์ $match
๋จ๊ณ์ ์ผ๋ถ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค. ์ถ๊ฐ๋ $match
๋จ๊ณ๊ฐ ํ์ดํ๋ผ์ธ ์์ ๋ถ๋ถ์ ์๋ ๊ฒฝ์ฐ, ์ง๊ณ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ๋ฟ๋ง ์๋๋ผ ์ปฌ๋ ์
์ ์ฟผ๋ฆฌํ์ฌ ํ์ดํ๋ผ์ธ์ ๋ค์ด๊ฐ๋ ๋ฌธ์ ์๋ฅผ ์ ํํ ์ ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ์ธ๋ฑ์ค ๋ฐ ๋ฌธ์ ํํฐ๋ก ์ฑ๋ฅ ํฅ์์ ์ฐธ์กฐํ์ธ์.
์๋ฅผ ๋ค์ด ํ์ดํ๋ผ์ธ์ด ๋ค์๊ณผ ๊ฐ์ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋์ด ์๋ ๊ฒฝ์ฐ์ ๋๋ค.
{ $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } }, { $match: { year: 2014, category: { $ne: "Z" } } }
์ตํฐ๋ง์ด์ ๋ $redact
๋จ๊ณ ์์ ๋์ผํ $match
๋จ๊ณ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
{ $match: { year: 2014 } }, { $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } }, { $match: { year: 2014, category: { $ne: "Z" } } }
$project
/$unset
+ ์ํ์ค $skip
์ต์ ํ
$project
๋๋ $unset
๋ค์ $skip
์ด ์ค๋ ์ํ์ค๊ฐ ์๋ ๊ฒฝ์ฐ $skip
์ $project
์์ผ๋ก ์ด๋ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ํ์ดํ๋ผ์ธ์ด ๋ค์๊ณผ ๊ฐ์ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋์ด ์๋ ๊ฒฝ์ฐ์
๋๋ค.
{ $sort: { age : -1 } }, { $project: { status: 1, name: 1 } }, { $skip: 5 }
์ต์ ํ ๋จ๊ณ์์ ์ตํฐ๋ง์ด์ ๋ ์ํ์ค๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณํํฉ๋๋ค.
{ $sort: { age : -1 } }, { $skip: 5 }, { $project: { status: 1, name: 1 } }
ํ์ดํ๋ผ์ธ ํตํฉ ์ต์ ํ
๊ฐ๋ฅํ ๊ฒฝ์ฐ ์ต์ ํ ๋จ๊ณ์์๋ ํ์ดํ๋ผ์ธ ๋จ๊ณ๋ฅผ ์ด์ ๋จ๊ณ๋ก ๋ณํฉํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ณํฉ์ ์ํ์ค ์ฌ์ ๋ ฌ ์ต์ ํ ํ์ ๋ฐ์ํฉ๋๋ค.
$sort
+ $limit
๋ณํฉ
$sort
๊ฐ $limit
์์ ์ฌ ๋, ๋ฌธ์ ์๋ฅผ ์์ ํ๋ ์ค๊ฐ ๋จ๊ณ๊ฐ ์๋ ๊ฒฝ์ฐ ์ตํฐ๋ง์ด์ ๋ $limit
์ $sort
๋ก ๋ณํฉํ ์ ์์ต๋๋ค (๋ฌธ์ ์๋ฅผ ์์ ํ๋ ์ค๊ฐ ๋จ๊ณ์ ์:$unwind
, $group
). $sort
๋จ๊ณ์ $limit
๋จ๊ณ ์ฌ์ด์ ๋ฌธ์ ์๋ฅผ ๋ณ๊ฒฝํ๋ ํ์ดํ๋ผ์ธ ๋จ๊ณ๊ฐ ์๋ ๊ฒฝ์ฐ MongoDB๋ $limit
์ $sort
๋ก ๋ณํฉํ์ง ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ํ์ดํ๋ผ์ธ์ด ๋ค์๊ณผ ๊ฐ์ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋์ด ์๋ ๊ฒฝ์ฐ์ ๋๋ค.
{ $sort : { age : -1 } }, { $project : { age : 1, status : 1, name : 1 } }, { $limit: 5 }
์ต์ ํ ๋จ๊ณ์์ ์ตํฐ๋ง์ด์ ๋ ์ํ์ค๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณํฉํฉ๋๋ค.
{ "$sort" : { "sortKey" : { "age" : -1 }, "limit" : NumberLong(5) } }, { "$project" : { "age" : 1, "status" : 1, "name" : 1 } }
์ด๋ ๊ฒ ํ๋ฉด ์ ๋ ฌ ์์
์ด ์งํ๋๋ฉด์ ์์ n
๊ฐ์ ๊ฒฐ๊ณผ๋ง ์ ์ง๋๊ณ (์ฌ๊ธฐ์ n
์ ์ง์ ๋ ํ๊ณ), MongoDB๋ ๋ฉ๋ชจ๋ฆฌ[1]์ n
๊ฐ์ ํญ๋ชฉ๋ง ์ ์ฅํ๋ฉด ๋ฉ๋๋ค. ์์ธํ ๋ด์ฉ์ $sort
์ฐ์ฐ์ ๋ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
์ฐธ๊ณ
$skip์ ์ฌ์ฉํ ์ํ์ค ์ต์ ํ
[1] | allowDiskUse ์ด true ์ด๊ณ n ํญ๋ชฉ์ด ์ง๊ณ ๋ฉ๋ชจ๋ฆฌ ์ ํ์ ์ด๊ณผํ๋ ๊ฒฝ์ฐ์๋ ์ต์ ํ๋ ๊ณ์ ์ ์ฉ๋ฉ๋๋ค. |
$limit
+ $limit
๋ณํฉ
$limit
์ด ๋ค๋ฅธ $limit
๋ฐ๋ก ๋ค์ ์ค๋ ๊ฒฝ์ฐ, ๋ ๋จ๊ณ๋ ๋ ์ด๊ธฐ ์ ํ ์๋ ์ค ๋ ์์ ์ ํ ๊ฐ์ ๊ฐ์ง ๋จ์ผ $limit
์ผ๋ก ํฉ์ณ์ง ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ํ์ดํ๋ผ์ธ์ ๋ค์๊ณผ ๊ฐ์ ์ํ์ค๋ฅผ ํฌํจํฉ๋๋ค.
{ $limit: 100 }, { $limit: 10 }
๊ทธ๋ฐ ๋ค์ ๋ ๋ฒ์งธ $limit
๋จ๊ณ๋ ์ฒซ ๋ฒ์งธ $limit
๋จ๊ณ๋ก ํฉ์ณ์ง๊ณ , ์ ํ ๊ฐ์ด ๋ ์ด๊ธฐ ์ ํ ๊ฐ 100
๊ณผ 10
์ค ์ต์๊ฐ์ธ 10
์ธ ์ ํ์ ๊ฐ์ง ๋จ์ผ $limit
๋จ๊ณ๋ฅผ ๊ฒฐ๊ณผ๋ก ๊ฐ๊ฒ ๋ฉ๋๋ค.
{ $limit: 10 }
$skip
+ $skip
๋ณํฉ
$skip
์ด ๋ค๋ฅธ $skip
๋ฐ๋ก ๋ค์ ์ค๋ ๊ฒฝ์ฐ, ๋ ๋จ๊ณ๋ ์ด๊ธฐ ์คํต ์๋์ ํฉ์ ์คํต ๊ฐ์ผ๋ก ํ๋ ๋จ์ผ $skip
์ผ๋ก ํฉ์ณ์ง ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ํ์ดํ๋ผ์ธ์ ๋ค์๊ณผ ๊ฐ์ ์ํ์ค๋ฅผ ํฌํจํฉ๋๋ค.
{ $skip: 5 }, { $skip: 2 }
๊ทธ๋ฐ ๋ค์ ๋ ๋ฒ์งธ $skip
๋จ๊ณ๊ฐ ์ฒซ ๋ฒ์งธ $skip
๋จ๊ณ๋ก ํฉ์ณ์ ธ ์คํต ์๋์ด ๋ ์ด๊ธฐ ์คํต 5
์ 2
์ ํฉ์ธ 7
์ ๊ฐ์ง ๋จ์ผ $skip
๋จ๊ณ๋ฅผ ๊ฒฐ๊ณผ๋ก ๋ณ๊ฒ ๋ฉ๋๋ค.
{ $skip: 7 }
$match
+ $match
๋ณํฉ
$match
๊ฐ ๋ค๋ฅธ $match
๋ฐ๋ก ๋ค์ ์ค๋ ๊ฒฝ์ฐ, ๋ ๋จ๊ณ๋ ์กฐ๊ฑด์ $and
์ ์ฌ์ฉํ์ฌ ๊ฒฐํฉํ๋ ๋จ์ผ $match
๋ก ํฉ์ณ์ง ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ํ์ดํ๋ผ์ธ์ ๋ค์๊ณผ ๊ฐ์ ์ํ์ค๋ฅผ ํฌํจํฉ๋๋ค.
{ $match: { year: 2014 } }, { $match: { status: "A" } }
๊ทธ๋ฐ ๋ค์ ๋ ๋ฒ์งธ $match
๋จ๊ณ๊ฐ ์ฒซ ๋ฒ์งธ $match
๋จ๊ณ๋ก ํฉ์ณ์ ธ ๋จ์ผ $match
๋จ๊ณ๊ฐ ๋ ์ ์์ต๋๋ค.
{ $match: { $and: [ { "year" : 2014 }, { "status" : "A" } ] } }
$lookup
, $unwind
๋ฐ $match
๋ณํฉ
$unwind
๊ฐ ๋ค๋ฅธ $lookup
๋ฐ๋ก ๋ค์ ์ค๊ณ , $unwind
๊ฐ $lookup
์ as
ํ๋์์ ์๋ํ๋ ๊ฒฝ์ฐ, ์ตํฐ๋ง์ด์ ๋ $unwind
๋ฅผ $lookup
๋จ๊ณ์ ๋ณํฉํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํฐ ์ค๊ฐ ๋ฌธ์๊ฐ ์์ฑ๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค. ๋ํ $unwind
์ ๋ค์ $lookup
์ as
ํ์ ํ๋์ ์๋ $match
๊ฐ ์ค๋ ๊ฒฝ์ฐ, ์ตํฐ๋ง์ด์ ๋ $match
๋ ๋ณํฉํฉ๋๋ค.
์๋ฅผ ๋ค์ด ํ์ดํ๋ผ์ธ์ ๋ค์๊ณผ ๊ฐ์ ์ํ์ค๋ฅผ ํฌํจํฉ๋๋ค.
{ $lookup: { from: "otherCollection", as: "resultingArray", localField: "x", foreignField: "y" } }, { $unwind: "$resultingArray" }, { $match: { "resultingArray.foo": "bar" } }
์ตํฐ๋ง์ด์ ๋ $unwind
๋ฐ $match
๋จ๊ณ๋ฅผ $lookup
๋จ๊ณ๋ก ํตํฉํฉ๋๋ค. explain
์ต์
์ ์ฌ์ฉํ์ฌ ์ง๊ณ๋ฅผ ์คํํ๋ฉด explain
์ถ๋ ฅ์ ๋ณํฉ๋ ๋จ๊ณ๊ฐ ํ์๋ฉ๋๋ค.
{ $lookup: { from: "otherCollection", as: "resultingArray", localField: "x", foreignField: "y", let: {}, pipeline: [ { $match: { "foo": { "$eq": "bar" } } } ], unwinding: { "preserveNullAndEmptyArrays": false } } }
๊ณํ ์ค๋ช ์์ ์ด ์ต์ ํ๋ ํ์ดํ๋ผ์ธ์ ํ์ธํ ์ ์์ต๋๋ค.
์ด์ explain
์ถ๋ ฅ์ ํ์๋ unwinding
ํ๋๋ $unwind
๋จ๊ณ์ ๋ค๋ฆ
๋๋ค. unwinding
ํ๋๋ ํ์ดํ๋ผ์ธ์ด ๋ด๋ถ์ ์ผ๋ก ์ต์ ํ๋๋ ๋ฐฉ์์ ๋ณด์ฌ์ค๋๋ค. $unwind
๋จ๊ณ๋ ์
๋ ฅ ๋ฌธ์์์ ๋ฐฐ์ด ํ๋๋ฅผ ๋ถํดํ๊ณ ๊ฐ ์์์ ๋ํ ๋ฌธ์๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
์ฌ๋กฏ ๊ธฐ๋ฐ ์ฟผ๋ฆฌ ์คํ ์์ง ํ์ดํ๋ผ์ธ ์ต์ ํ
MongoDB๋ ์ฌ๋กฏ ๊ธฐ๋ฐ ์ฟผ๋ฆฌ ์คํ ์์ง์ ์ฌ์ฉํ์ฌ ๊ตฌ์ฒด์ ์ธ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋ ํน์ ํ์ดํ๋ผ์ธ ๋จ๊ณ๋ฅผ ์คํํ ์ ์์ต๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ ๊ธฐ์กด ์ฟผ๋ฆฌ ์์ง์ ๋นํด ์ฑ๋ฅ์ด ํฅ์๋๊ณ CPU ๋ฐ ๋ฉ๋ชจ๋ฆฌ ๋น์ฉ์ด ๋ฎ์ต๋๋ค.
์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ด ์ฌ์ฉ๋๋์ง ํ์ธํ๋ ค๋ฉด explain
์ต์
์ ์ฌ์ฉํ์ฌ ์ง๊ณ๋ฅผ ์คํํฉ๋๋ค. ์ด ์ต์
์ ์ง๊ณ์ ์ฟผ๋ฆฌ ๊ณํ์ ๋ํ ์ ๋ณด๋ฅผ ์ถ๋ ฅํฉ๋๋ค. ์ง๊ณ์ explain
์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ธํ ๋ด์ฉ์ ์ง๊ณ ํ์ดํ๋ผ์ธ ์์
์ ๋ํ ์ ๋ณด ๋ฐํ์ ์ฐธ์กฐํ์ธ์.
๋ค์ ์น์ ์ ๋ค์์ ์ค๋ช ํฉ๋๋ค.
์ง๊ณ์ ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ๋ํ ์กฐ๊ฑด
์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ด ์ฌ์ฉ๋์๋์ง ํ์ธํ๋ ๋ฐฉ๋ฒ
$group
์ต์ ํ
๋ฒ์ 5.2์ ์ถ๊ฐ๋์์ต๋๋ค.
๋ฒ์ 5.2๋ถํฐ MongoDB๋ ๋ค์ ๋ ๊ฒฝ์ฐ ์ค ํ๋์ ํด๋นํ ๋ $group
๋จ๊ณ๋ฅผ ์คํํ๊ธฐ ์ํด ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์ฟผ๋ฆฌ ์์ง์ ์ฌ์ฉํฉ๋๋ค.
$group
ํ์ดํ๋ผ์ธ์ ์ฒซ ๋ฒ์งธ ๋จ๊ณ์ ๋๋ค.ํ์ดํ๋ผ์ธ์ ๋ชจ๋ ์ด์ ๋จ๊ณ๋ ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ ์ํด ์คํ๋ ์๋ ์์ต๋๋ค.
์ฌ๋กฏ ๊ธฐ๋ฐ ์ฟผ๋ฆฌ ์คํ ์์ง์ด $group
์ ์ฌ์ฉ๋ ๋ explain ๊ฒฐ๊ณผ์๋ queryPlanner.winningPlan.queryPlan.stage:
"GROUP"
์ด ํฌํจ๋ฉ๋๋ค.
queryPlanner
๊ฐ์ฒด์ ์์น๋ ํ์ดํ๋ผ์ธ์ด $group
๋จ๊ณ ์ดํ์ ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ ์ฌ์ฉํ์ฌ ์คํํ ์ ์๋ ๋จ๊ณ๋ฅผ ํฌํจํ๊ณ ์๋์ง ์ฌ๋ถ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
๋ง์ฝ
$group
์ด ๋ง์ง๋ง ๋จ๊ณ์ด๊ฑฐ๋$group
์ดํ์ ๋ชจ๋ ๋จ๊ณ๊ฐ ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ ์ฌ์ฉํ์ฌ ์คํ๋ ์ ์๋ค๋ฉด,queryPlanner
๊ฐ์ฒด๋ ์ต์์explain
์ถ๋ ฅ ๊ฐ์ฒด (explain.queryPlanner
)์ ์์นํฉ๋๋ค.ํ์ดํ๋ผ์ธ์
$group
์ดํ์ ์ฌ๋กฏ ๊ธฐ๋ฐ ์์ง์ ์ฌ์ฉํ์ฌ ์คํํ ์ ์๋ ๋จ๊ณ๊ฐ ํฌํจ๋์ด ์๋ ๊ฒฝ์ฐ,queryPlanner
๊ฐ์ฒด๋explain.stages[0].$cursor.queryPlanner
์ ์์นํฉ๋๋ค.
$lookup
์ต์ ํ
๋ฒ์ 6.0์ ์ถ๊ฐ.
๋ฒ์ 6.0๋ถํฐ, ํ์ดํ๋ผ์ธ์ ๋ชจ๋ ์ ํ ๋จ๊ณ๊ฐ ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ผ๋ก ์คํ๋ ์ ์๊ณ ๋ค์ ์กฐ๊ฑด ์ค ํ๋๋ผ๋ ํด๋น๋์ง ์๋ ๊ฒฝ์ฐ, MongoDB๋ $lookup
๋จ๊ณ๋ฅผ ์คํํ๊ธฐ ์ํด ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์ฟผ๋ฆฌ ์์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
$lookup
์์ ์ ์กฐ์ธ๋ ์ปฌ๋ ์ ์์ ํ์ดํ๋ผ์ธ์ ์คํํฉ๋๋ค. ์ด๋ฌํ ์ข ๋ฅ์ ์์ ์ ์๋ฅผ ๋ณด๋ ค๋ฉด ์กฐ์ธ๋ ์ปฌ๋ ์ ์์์ ์กฐ์ธ ์กฐ๊ฑด ๋ฐ ํ์ ์ฟผ๋ฆฌ๋ฅผ ์ฐธ์กฐํ์ธ์.$lookup
์localField
๋๋foreignField
๋ ์ซ์ ๊ตฌ์ฑ ์์๋ฅผ ์ง์ ํฉ๋๋ค. ์์:{ localField: "restaurant.0.review" }
ํ์ดํ๋ผ์ธ์์
$lookup
์from
ํ๋๋ ๋ทฐ ๋๋ ์ค๋ ์ปฌ๋ ์ ์ ์ง์ ํฉ๋๋ค.
์ฌ๋กฏ ๊ธฐ๋ฐ ์ฟผ๋ฆฌ ์คํ ์์ง์ด $lookup
์ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ explain ๊ฒฐ๊ณผ์๋ queryPlanner.winningPlan.queryPlan.stage: "EQ_LOOKUP"
์ด ํฌํจ๋ฉ๋๋ค. EQ_LOOKUP
์ '๋๋ฑ์ฑ ์กฐํ (equality lookup)'๋ฅผ ์๋ฏธํฉ๋๋ค.
queryPlanner
๊ฐ์ฒด์ ์์น๋ ํ์ดํ๋ผ์ธ์ด $lookup
๋จ๊ณ ์ดํ์ ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ ์ฌ์ฉํ์ฌ ์คํํ ์ ์๋ ๋จ๊ณ๋ฅผ ํฌํจํ๊ณ ์๋์ง ์ฌ๋ถ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
๋ง์ฝ
$lookup
์ด ๋ง์ง๋ง ๋จ๊ณ์ด๊ฑฐ๋$lookup
์ดํ์ ๋ชจ๋ ๋จ๊ณ๊ฐ ์ฌ๋กฏ ๊ธฐ๋ฐ ์คํ ์์ง์ ์ฌ์ฉํ์ฌ ์คํ๋ ์ ์๋ค๋ฉด,queryPlanner
๊ฐ์ฒด๋ ์ต์์explain
์ถ๋ ฅ ๊ฐ์ฒด (explain.queryPlanner
)์ ์์นํฉ๋๋ค.ํ์ดํ๋ผ์ธ์
$lookup
์ดํ์ ์ฌ๋กฏ ๊ธฐ๋ฐ ์์ง์ ์ฌ์ฉํ์ฌ ์คํํ ์ ์๋ ๋จ๊ณ๊ฐ ํฌํจ๋์ด ์๋ ๊ฒฝ์ฐ,queryPlanner
๊ฐ์ฒด๋explain.stages[0].$cursor.queryPlanner
์ ์์นํฉ๋๋ค.
์ธ๋ฑ์ค ๋ฐ ๋ฌธ์ ํํฐ๋ก ์ฑ๋ฅ ํฅ์
๋ค์ ์น์ ์์๋ ์ธ๋ฑ์ค์ ๋ฌธ์ ํํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ง๊ณ ์ฑ๋ฅ์ ํฅ์ํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
Indexes
์ง๊ณ ํ์ดํ๋ผ์ธ์ ์ ๋ ฅ ์ปฌ๋ ์ ์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ์ ๊ฐ์ ํ ์ ์์ต๋๋ค. ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๋จ๊ณ๊ฐ ์ฒ๋ฆฌํ๋ ๋ฌธ์์ ์์ด ์ ํ๋ฉ๋๋ค. ์ด์์ ์ผ๋ก๋ ์ธ๋ฑ์ค๊ฐ ๋จ๊ณ ์ฟผ๋ฆฌ๋ฅผ ์ปค๋ฒํ ์ ์์ต๋๋ค. ์ปค๋ฒ๋ ์ฟผ๋ฆฌ๋ ํนํ ์ฑ๋ฅ์ด ๋์๋ฐ, ์ด๋ ์ธ๋ฑ์ค๊ฐ ์ผ์นํ๋ ๋ชจ๋ ๋ฌธ์๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์๋ฅผ ๋ค์ด $match
, $sort
, $group
๋ก ๊ตฌ์ฑ๋ ํ์ดํ๋ผ์ธ์ ๋ชจ๋ ๋จ๊ณ์์ ์ธ๋ฑ์ค์ ์ด์ ์ ๋๋ฆด ์ ์์ต๋๋ค.
$match
์ฟผ๋ฆฌ ํ๋์ ์ธ๋ฑ์ค๋ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์๋ณํฉ๋๋ค.์ ๋ ฌ ํ๋์ ์ธ๋ฑ์ค๋
$sort
๋จ๊ณ์ ๋ํด ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฌ๋ ์์๋ก ๋ฐํํฉ๋๋ค.$sort
์์์ ์ผ์นํ๋ ๊ทธ๋ฃนํ ํ๋์ ์ธ๋ฑ์ค๋$group
๋จ๊ณ์ ํ์ํ ๋ชจ๋ ํ๋ ๊ฐ์ ๋ฐํํ๋ฉฐ, ์ด๋ฅผ ์ปค๋ฒ๋ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ญ๋๋ค.
ํ์ดํ๋ผ์ธ์ด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ค๋ฉด ์ฟผ๋ฆฌ ๊ณํ์ ๊ฒํ ํ๊ณ IXSCAN
๋๋ DISTINCT_SCAN
๊ณํ์ด ์๋์ง ์ฐพ์๋ณด์์ผ ํฉ๋๋ค.
์ฐธ๊ณ
๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ฟผ๋ฆฌ ํ๋๋๋ ์ธ๋ฑ์ค ํค ๊ฐ๋น ํ๋์ ๋ฌธ์๋ฅผ ๋ฐํํ๋ DISTINCT_SCAN
์ธ๋ฑ์ค ๊ณํ์ ์ฌ์ฉํฉ๋๋ค. ํค ๊ฐ๋น ์ฌ๋ฌ ๋ฌธ์๊ฐ ์๋ ๊ฒฝ์ฐ DISTINCT_SCAN
์ด IXSCAN
๋ณด๋ค ๋น ๋ฅด๊ฒ ์คํ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ธ๋ฑ์ค ์ค์บ ๋งค๊ฐ๋ณ์๋ DISTINCT_SCAN
๊ณผ IXSCAN
์ ์๊ฐ ๋น๊ต์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
์ง๊ณ ํ์ดํ๋ผ์ธ์ ์ด๊ธฐ ๋จ๊ณ์์๋ ์ฟผ๋ฆฌ ํ๋๋ฅผ ์ธ๋ฑ์ฑํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์. ์ธ๋ฑ์ค๋ฅผ ํ์ฉํ ์ ์๋ ๋จ๊ณ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
$match
๋จ๊ณ$match
๋จ๊ณ ๋์, ์๋ฒ๋ ์ฟผ๋ฆฌ ํ๋๋์ ์ต์ ํ ์ดํ ํ์ดํ๋ผ์ธ์ ์ฒซ ๋ฒ์งธ ๋จ๊ณ๊ฐ$match
์ผ ๊ฒฝ์ฐ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.$sort
๋จ๊ณ$sort
๋จ๊ณ ๋์, ํด๋น ๋จ๊ณ๊ฐ$project
,$unwind
, ๋๋$group
๋จ๊ณ๋ฅผ ์์์ง ์๋ ๊ฒฝ์ฐ ์๋ฒ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.$group
๋จ๊ณ$group
๋จ๊ณ ๋์, ํด๋น ๋จ๊ณ๊ฐ ๋ค์ ๋ ์กฐ๊ฑด์ ๋ชจ๋ ์ถฉ์กฑํ๋ ๊ฒฝ์ฐ ์๋ฒ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ๊ทธ๋ฃน์$first
๋๋$last
๋ฌธ์๋ฅผ ๋น ๋ฅด๊ฒ ์ฐพ์ ์ ์์ต๋๋ค.ํ์ดํ๋ผ์ธ์ด ๋์ผํ ํ๋์ ์ํด
sorts
ํ๊ณgroups
ํฉ๋๋ค.$group
๋จ๊ณ์์๋$first
๋๋$last
๋์ฐ๊ธฐ (accumulator) ์ฐ์ฐ์๋ง ์ฌ์ฉํฉ๋๋ค.
์๋ฅผ ๋ณด๋ ค๋ฉด $group ์ฑ๋ฅ ์ต์ ํ๋ฅผ ์ฐธ์กฐํ์ธ์.
$geoNear
๋จ๊ณ- ์๋ฒ๋ ํญ์
$geoNear
๋จ๊ณ์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด ๋จ๊ณ๋ ์ง๋ฆฌ์ ๊ณต๊ฐ ์ธ๋ฑ์ค๋ฅผ ํ์๋ก ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋ํ ์์ ๋์ง ์์ ๋ค๋ฅธ ์ปฌ๋ ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ ํ์ดํ๋ผ์ธ์ ํ๋ฐ ๋จ๊ณ์์๋ ์ต์ ํ๋ฅผ ์ํด ํด๋น ์ปฌ๋ ์ ์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋จ๊ณ์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค.
๋ฌธ์ ํํฐ
์ง๊ณ ์์ ์ ์ปฌ๋ ์ ๋ฌธ์์ ํ์ ์งํฉ๋ง ํ์๋ก ํ๋ ๊ฒฝ์ฐ, ๋ฌธ์๋ฅผ ๋จผ์ ํํฐ๋งํฉ๋๋ค.
$match
,$limit
๊ทธ๋ฆฌ๊ณ$skip
๋จ๊ณ๋ฅผ ์ฌ์ฉํ์ฌ ํ์ดํ๋ผ์ธ์ผ๋ก ๋ค์ด์ค๋ ๋ฌธ์๋ฅผ ์ ํํฉ๋๋ค.๊ฐ๋ฅํ๋ฉด ์ปฌ๋ ์ ์์ ์ผ์นํ๋ ๋ฌธ์๋ฅผ ์ค์บํ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ํ์ดํ๋ผ์ธ์ ์์ ๋ถ๋ถ์
$match
๋ฐฐ์นํ์ธ์.ํ์ดํ๋ผ์ธ์ ์์ ๋ถ๋ถ์
$match
๋ค์์$sort
๊ฐ ์ค๋ ๊ฒ์ ์ ๋ ฌ์ด ํฌํจ๋ ๋จ์ผ ์ฟผ๋ฆฌ์ ๋์ผํ๋ฉฐ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์์
$sort
+ $skip
+ ์ํ์ค $limit
ํ์ดํ๋ผ์ธ์ $sort
๋ค์์ $skip
์ด ์ค๊ณ , ๊ทธ ๋ค์์ $limit
์ด ์ค๋ ์ํ์ค๋ฅผ ํฌํจํ๊ณ ์์ต๋๋ค.
{ $sort: { age : -1 } }, { $skip: 10 }, { $limit: 5 }
์ตํฐ๋ง์ด์ ๋ $sort
+ $limit
๋ณํฉ์ ์ํํ์ฌ ์ํ์ค๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณํํฉ๋๋ค.
{ "$sort" : { "sortKey" : { "age" : -1 }, "limit" : NumberLong(15) } }, { "$skip" : NumberLong(10) }
MongoDB๋ ์ฌ์ ๋ ฌ์ ํตํด $limit
์ ์์ ์ฆ๊ฐ์ํต๋๋ค.
๋ค์๋ ์ฐธ์กฐํ์ธ์.
explain
์ต์
db.collection.aggregate()