Docs Menu

์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ์ตœ์ ํ™”

์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ์ž‘์—…์—๋Š” ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์œ„ํ•ด ํŒŒ์ดํ”„๋ผ์ธ์„ ์žฌ๊ตฌ์„ฑํ•˜๋Š” ์ตœ์ ํ™” ๋‹จ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ ํŠน์ • ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์„ ์–ด๋–ป๊ฒŒ ๋ณ€ํ™˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด explain ์˜ต์…˜์„ db.collection.aggregate() ๋ฉ”์„œ๋“œ์— ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

์ตœ์ ํ™”๋Š” ๋ฆด๋ฆฌ์Šค ๊ฐ„์— ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ตœ์ ํ™” ๋‹จ๊ณ„์—์„œ ์ˆ˜ํ–‰๋˜๋Š” ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ์ตœ์ ํ™”์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋Š” ๊ฒƒ ์™ธ์—๋„ ์ธ๋ฑ์Šค ๋ฐ ๋ฌธ์„œ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

MongoDB Atlas์—์„œ ํ˜ธ์ŠคํŒ…๋˜๋Š” ๋ฐฐํฌ์— ๋Œ€ํ•ด UI์—์„œ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ๋ฌธ์„œ ํ•„๋“œ์˜ ํ•˜์œ„ ์ง‘ํ•ฉ๋งŒ ํ•„์š”ํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํŒŒ์ดํ”„๋ผ์ธ์€ ํ•ด๋‹น ํ•„๋“œ๋งŒ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํŒŒ์ดํ”„๋ผ์ธ์„ ํ†ต๊ณผํ•˜๋Š” ๋ฐ์ดํ„ฐ ์–‘์ด ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

$project ๋‹จ๊ณ„๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์—ฌ์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ํด๋ผ์ด์–ธํŠธ์— ๋ฐ˜ํ™˜ํ•  ํ•„๋“œ๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

ํŒŒ์ดํ”„๋ผ์ธ์˜ ์‹œ์ž‘ ๋˜๋Š” ์ค‘๊ฐ„์— $project ๋‹จ๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ›„์† ํŒŒ์ดํ”„๋ผ์ธ ๋‹จ๊ณ„๋กœ ์ „๋‹ฌ๋˜๋Š” ํ•„๋“œ ์ˆ˜๋ฅผ ์ค„์ด๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ด ์ตœ์ ํ™”๋ฅผ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๋ฏ€๋กœ ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ์…˜ ๋‹จ๊ณ„($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๊ฐ€ ์žˆ๋Š” ์‹œํ€€์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ •๋ ฌํ•  ๊ฐœ์ฒด ์ˆ˜๋ฅผ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•ด $match๋ฅผ $sort ์•ž์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ดํ”„๋ผ์ธ์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

{ $sort: { age : -1 } },
{ $match: { status: 'A' } }

์ตœ์ ํ™” ๋‹จ๊ณ„์—์„œ ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” ์‹œํ€€์Šค๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{ $match: { status: 'A' } },
{ $sort: { age : -1 } }

๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ํŒŒ์ดํ”„๋ผ์ธ์— $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์ด ์˜ค๋Š” ์‹œํ€€์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ $skip์€ $project ์•ž์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ดํ”„๋ผ์ธ์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹จ๊ณ„๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

{ $sort: { age : -1 } },
{ $project: { status: 1, name: 1 } },
{ $skip: 5 }

์ตœ์ ํ™” ๋‹จ๊ณ„์—์„œ ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” ์‹œํ€€์Šค๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{ $sort: { age : -1 } },
{ $skip: 5 },
{ $project: { status: 1, name: 1 } }

๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ์ตœ์ ํ™” ๋‹จ๊ณ„์—์„œ๋Š” ํŒŒ์ดํ”„๋ผ์ธ ๋‹จ๊ณ„๋ฅผ ์ด์ „ ๋‹จ๊ณ„๋กœ ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋ณ‘ํ•ฉ์€ ์‹œํ€€์Šค ์žฌ์ •๋ ฌ ์ตœ์ ํ™” ํ›„์— ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

$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์„ ์‚ฌ์šฉํ•œ ์‹œํ€€์Šค ์ตœ์ ํ™”

$sort์™€ $limit ๋‹จ๊ณ„ ์‚ฌ์ด์— $skip ๋‹จ๊ณ„๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ MongoDB๋Š” $limit๋ฅผ $sort ๋‹จ๊ณ„๋กœ ํ†ตํ•ฉํ•˜๊ณ  $limit ๊ฐ’์„ $skip ์–‘๋งŒํผ ๋Š˜๋ฆฝ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋ณด๋ ค๋ฉด $sort + $skip + $limit ์‹œํ€€์Šค๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

[1] allowDiskUse์ด true์ด๊ณ  n ํ•ญ๋ชฉ์ด ์ง‘๊ณ„ ๋ฉ”๋ชจ๋ฆฌ ์ œํ•œ์„ ์ดˆ๊ณผํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ์ตœ์ ํ™”๋Š” ๊ณ„์† ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

$limit์ด ๋‹ค๋ฅธ $limit ๋ฐ”๋กœ ๋’ค์— ์˜ค๋Š” ๊ฒฝ์šฐ, ๋‘ ๋‹จ๊ณ„๋Š” ๋‘ ์ดˆ๊ธฐ ์ œํ•œ ์ˆ˜๋Ÿ‰ ์ค‘ ๋” ์ž‘์€ ์ œํ•œ ๊ฐ’์„ ๊ฐ€์ง„ ๋‹จ์ผ $limit์œผ๋กœ ํ•ฉ์ณ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ดํ”„๋ผ์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹œํ€€์Šค๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

{ $limit: 100 },
{ $limit: 10 }

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‘ ๋ฒˆ์งธ $limit ๋‹จ๊ณ„๋Š” ์ฒซ ๋ฒˆ์งธ $limit ๋‹จ๊ณ„๋กœ ํ•ฉ์ณ์ง€๊ณ , ์ œํ•œ ๊ฐ’์ด ๋‘ ์ดˆ๊ธฐ ์ œํ•œ ๊ฐ’ 100๊ณผ 10 ์ค‘ ์ตœ์†Œ๊ฐ’์ธ 10์ธ ์ œํ•œ์„ ๊ฐ€์ง„ ๋‹จ์ผ $limit ๋‹จ๊ณ„๋ฅผ ๊ฒฐ๊ณผ๋กœ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

{ $limit: 10 }

$skip์ด ๋‹ค๋ฅธ $skip ๋ฐ”๋กœ ๋’ค์— ์˜ค๋Š” ๊ฒฝ์šฐ, ๋‘ ๋‹จ๊ณ„๋Š” ์ดˆ๊ธฐ ์Šคํ‚ต ์ˆ˜๋Ÿ‰์˜ ํ•ฉ์„ ์Šคํ‚ต ๊ฐ’์œผ๋กœ ํ•˜๋Š” ๋‹จ์ผ $skip์œผ๋กœ ํ•ฉ์ณ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ดํ”„๋ผ์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹œํ€€์Šค๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

{ $skip: 5 },
{ $skip: 2 }

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‘ ๋ฒˆ์งธ $skip ๋‹จ๊ณ„๊ฐ€ ์ฒซ ๋ฒˆ์งธ $skip ๋‹จ๊ณ„๋กœ ํ•ฉ์ณ์ ธ ์Šคํ‚ต ์ˆ˜๋Ÿ‰์ด ๋‘ ์ดˆ๊ธฐ ์Šคํ‚ต 5์™€ 2์˜ ํ•ฉ์ธ 7์„ ๊ฐ€์ง„ ๋‹จ์ผ $skip ๋‹จ๊ณ„๋ฅผ ๊ฒฐ๊ณผ๋กœ ๋‚ณ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

{ $skip: 7 }

$match๊ฐ€ ๋‹ค๋ฅธ $match ๋ฐ”๋กœ ๋’ค์— ์˜ค๋Š” ๊ฒฝ์šฐ, ๋‘ ๋‹จ๊ณ„๋Š” ์กฐ๊ฑด์„ $and์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฐํ•ฉํ•˜๋Š” ๋‹จ์ผ $match๋กœ ํ•ฉ์ณ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒŒ์ดํ”„๋ผ์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹œํ€€์Šค๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

{ $match: { year: 2014 } },
{ $match: { status: "A" } }

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‘ ๋ฒˆ์งธ $match ๋‹จ๊ณ„๊ฐ€ ์ฒซ ๋ฒˆ์งธ $match ๋‹จ๊ณ„๋กœ ํ•ฉ์ณ์ ธ ๋‹จ์ผ $match ๋‹จ๊ณ„๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

{ $match: { $and: [ { "year" : 2014 }, { "status" : "A" } ] } }

$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 ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ์ž‘์—…์— ๋Œ€ํ•œ ์ •๋ณด ๋ฐ˜ํ™˜์„ ์ฐธ์กฐํ•˜์„ธ์š”.

๋‹ค์Œ ์„น์…˜์€ ๋‹ค์Œ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

  • ์ง‘๊ณ„์— ์Šฌ๋กฏ ๊ธฐ๋ฐ˜ ์‹คํ–‰ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ์กฐ๊ฑด

  • ์Šฌ๋กฏ ๊ธฐ๋ฐ˜ ์‹คํ–‰ ์—”์ง„์ด ์‚ฌ์šฉ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•

๋ฒ„์ „ 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์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค.

๋ฒ„์ „ 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์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ธ๋ฑ์Šค์™€ ๋ฌธ์„œ ํ•„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง‘๊ณ„ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์€ ์ž…๋ ฅ ์ปฌ๋ ‰์…˜์˜ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹จ๊ณ„๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฌธ์„œ์˜ ์–‘์ด ์ œํ•œ๋ฉ๋‹ˆ๋‹ค. ์ด์ƒ์ ์œผ๋กœ๋Š” ์ธ๋ฑ์Šค๊ฐ€ ๋‹จ๊ณ„ ์ฟผ๋ฆฌ๋ฅผ ์ปค๋ฒ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค๋ฒ„๋œ ์ฟผ๋ฆฌ๋Š” ํŠนํžˆ ์„ฑ๋Šฅ์ด ๋†’์€๋ฐ, ์ด๋Š” ์ธ๋ฑ์Šค๊ฐ€ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด $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: { age : -1 } },
{ $skip: 10 },
{ $limit: 5 }

์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” $sort + $limit ๋ณ‘ํ•ฉ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์‹œํ€€์Šค๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

{
"$sort" : {
"sortKey" : {
"age" : -1
},
"limit" : NumberLong(15)
}
},
{
"$skip" : NumberLong(10)
}

MongoDB๋Š” ์žฌ์ •๋ ฌ์„ ํ†ตํ•ด $limit์˜ ์–‘์„ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.

๋‹ค์Œ๋„ ์ฐธ์กฐํ•˜์„ธ์š”.