๋ฌธ์„œ ๋ฉ”๋‰ด
๋ฌธ์„œ ํ™ˆ
/
MongoDB ๋งค๋‰ด์–ผ
/ / /

db.collection.mapReduce()

์ด ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ

  • ๊ตฌ๋ฌธ
  • ์ถœ๋ ฅ
  • ์ œํ•œ ์‚ฌํ•ญ
  • ์ถ”๊ฐ€ ์ •๋ณด

์ฐธ๊ณ 

๋งต ๋ฆฌ๋“€์Šค์˜ ๋Œ€์•ˆ์œผ๋กœ์„œ์˜ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ

MongoDB 5 ๋ถ€ํ„ฐ ์‹œ์ž‘.0 ๋งต ๋ฆฌ๋“€์Šค ๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋งต ๋ฆฌ๋“€์Šค ๋Œ€์•ˆ์œผ๋กœ์„œ์˜ ์• ๊ทธ๋ฆฌ๊ฒŒ์ด์…˜ ํŒŒ์ดํ”„๋ผ์ธ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

db.collection.mapReduce(map,reduce, { <options> })

์ค‘์š”

Mongo์‰ฌ ๋ฐฉ๋ฒ•

์ด ํŽ˜์ด์ง€์—์„œ๋Š” mongosh ๋ฉ”์„œ๋“œ๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ช…๋ น ๋˜๋Š” Node.js์™€ ๊ฐ™์€ ์–ธ์–ด๋ณ„ ๋“œ๋ผ์ด๋ฒ„์— ๋Œ€ํ•œ ์„ค๋ช…์„œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ช…๋ น์— ๋Œ€ํ•ด์„œ๋Š” mapReduce ๋ช…๋ น์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

MongoDB API ๋“œ๋ผ์ด๋ฒ„์˜ ๊ฒฝ์šฐ ์–ธ์–ด๋ณ„ MongoDB ๋“œ๋ผ์ด๋ฒ„ ์„ค๋ช…์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์ฐธ๊ณ 

๋ทฐ๋Š” ๋งต ์ถ•์†Œ ์ž‘์—…์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ 

MongoDB๋Š” ์ž์„ธํ•œ ์ •๋ณด ํ‘œ์‹œ ์˜ต์…˜์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค.

๋ฒ„์ „ 4.2๋ถ€ํ„ฐ MongoDB๋Š” ๋‹ค์Œ์„ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ƒˆ ์ƒค๋“œ ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•˜๋Š” ๋งต ๋ฆฌ๋“€์Šค ์˜ต์…˜์€ ๋ฌผ๋ก  ๋งต ๋ฆฌ๋“€์Šค๋ฅผ ์œ„ํ•œ ์ƒค๋”ฉ ์˜ต์…˜๋„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ƒค๋“œ ์ปฌ๋ ‰์…˜์œผ๋กœ ์ถœ๋ ฅํ•˜๋ ค๋ฉด ๋จผ์ € ์ƒค๋“œ ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•˜์„ธ์š”. ๊ฒŒ๋‹ค๊ฐ€ MongoDB 4.2๋Š” ๊ธฐ์กด ์ƒค๋“œ ์ปฌ๋ ‰์…˜์˜ ๊ต์ฒด๋ฅผ ๋” ์ด์ƒ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

db.collection.mapReduce() ์˜ ๊ตฌ๋ฌธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

db.collection.mapReduce(
<map>,
<reduce>,
{
out: <collection>,
query: <document>,
sort: <document>,
limit: <number>,
finalize: <function>,
scope: <document>,
jsMode: <boolean>,
verbose: <boolean>,
bypassDocumentValidation: <boolean>
}
)

db.collection.mapReduce() ๋‹ค์Œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋งค๊ฐœ ๋ณ€์ˆ˜
์œ ํ˜•
์„ค๋ช…
map
JavaScript ๋˜๋Š” ๋ฌธ์ž์—ด

value ๋ฅผ key ์— ์—ฐ๊ฒฐํ•˜๊ฑฐ๋‚˜ '๋งคํ•‘'ํ•˜๊ณ  key ๋ฐ ๊ฐ’ pair ์„ ๋ฐฉ์ถœํ•˜๋Š” JavaScript ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ BSON type JavaScript(์˜ˆ: BSON type 13) ๋˜๋Š” ๋ฌธ์ž์—ด(์˜ˆ: BSON type 2).

์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ง€๋„ ๊ธฐ๋Šฅ์˜ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

reduce
JavaScript ๋˜๋Š” ๋ฌธ์ž์—ด

ํŠน์ • key ์™€ ์—ฐ๊ฒฐ๋œ ๋ชจ๋“  values ๋ฅผ ๋‹จ์ผ ๊ฐ์ฒด๋กœ '์ค„์ด๋Š”' JavaScript ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ BSON type JavaScript(์˜ˆ: BSON type 13) ๋˜๋Š” ๋ฌธ์ž์—ด(์˜ˆ: BSON type 2).

์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ฆฌ๋“€์Šค ํ•จ์ˆ˜์˜ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

options
๋ฌธ์„œ
db.collection.mapReduce()์— ์ถ”๊ฐ€ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ ํ‘œ์—์„œ๋Š” db.collection.mapReduce()๊ฐ€ ์ˆ˜๋ฝํ•  ์ˆ˜ ์žˆ๋Š” ์ถ”๊ฐ€ ์ธ์ˆ˜์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

ํ•„๋“œ
์œ ํ˜•
์„ค๋ช…
out
๋ฌธ์ž์—ด ๋˜๋Š” ๋ฌธ์„œ

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

์ž์„ธํ•œ ๋‚ด์šฉ์€ out ์˜ต์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”.

query
๋ฌธ์„œ
map ํ•จ์ˆ˜์— ์ž…๋ ฅ๋œ ๋ฌธ์„œ๋ฅผ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ์ฟผ๋ฆฌ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ํƒ ๊ธฐ์ค€์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
sort
๋ฌธ์„œ
์ž…๋ ฅ ๋ฌธ์„œ๋ฅผ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์€ ์ตœ์ ํ™”์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ •๋ ฌ ํ‚ค๋ฅผ ๋‚ด๋ณด๋‚ด๊ธฐ ํ‚ค์™€ ๋™์ผํ•˜๊ฒŒ ์ง€์ •ํ•˜์—ฌ ์ถ•์†Œ ์ž‘์—…์„ ์ค„์ด๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •๋ ฌ ํ‚ค๋Š” ์ด ์ปฌ๋ ‰์…˜์˜ ๊ธฐ์กด ์ธ๋ฑ์Šค์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
limit
์ˆซ์ž
map ํ•จ์ˆ˜์— ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๋ฌธ์„œ ์ˆ˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
finalize
JavaScript ๋˜๋Š” ๋ฌธ์ž์—ด

์„ ํƒ ์‚ฌํ•ญ. reduce ํ•จ์ˆ˜ ์ดํ›„์˜ ์ถœ๋ ฅ์„ ์ˆ˜์ •ํ•˜๋Š” JavaScript ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋ฅผ BSON type JavaScript(์˜ˆ: BSON type 13) ๋˜๋Š” ๋ฌธ์ž์—ด(์˜ˆ: BSON type 2).

์ž์„ธํ•œ ๋‚ด์šฉ์€ finalize ํ•จ์ˆ˜ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

scope
๋ฌธ์„œ
map, reduce ๋ฐ finalize ํ•จ์ˆ˜์—์„œ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ๊ธ€๋กœ๋ฒŒ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
jsMode
๋ถ€์šธ

map ํ•จ์ˆ˜์™€ reduce ํ•จ์ˆ˜ ์‹คํ–‰ ์‚ฌ์ด์— ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ BSON ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ๊ฐ’์€ false์ž…๋‹ˆ๋‹ค.

false์ธ ๊ฒฝ์šฐ:

  • ๋‚ด๋ถ€์ ์œผ๋กœ MongoDB๋Š” map ํ•จ์ˆ˜์—์„œ ๋‚ด๋ณด๋‚ธ JavaScript ๊ฐ์ฒด๋ฅผ BSON ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ด๋Ÿฌํ•œ BSON ๊ฐ์ฒด๋Š” reduce ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ JavaScript ๊ฐ์ฒด๋กœ ๋‹ค์‹œ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.

  • ๋งต ๋ฆฌ๋“€์Šค ์ž‘์—…์€ ์ค‘๊ฐ„ BSON ๊ฐ์ฒด๋ฅผ ์ž„์‹œ ๋””์Šคํฌ ์ƒ์˜ ์ €์žฅ์†Œ์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋งต ๋ฆฌ๋“€์Šค ์ž‘์—…์„ ์ž„์˜๋กœ ํฐ ๋ฐ์ดํ„ฐ ์„ธํŠธ์— ๋Œ€ํ•ด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

true์ธ ๊ฒฝ์šฐ:

  • ๋‚ด๋ถ€์ ์œผ๋กœ map ํ•จ์ˆ˜ ์ค‘์— ๋ฐฉ์ถœ๋œ JavaScript ๊ฐ์ฒด๋Š” JavaScript ๊ฐ์ฒด๋กœ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. reduce ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๊ฐ์ฒด๋ฅผ ๋ณ€ํ™˜ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์‹คํ–‰ ์†๋„๊ฐ€ ๋นจ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋งคํผ์˜ emit() ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๊ณ ์œ  key ์ธ์ˆ˜๊ฐ€ 500,000๊ฐœ ๋ฏธ๋งŒ์ธ ๊ฒฐ๊ณผ ์„ธํŠธ์—๋งŒ jsMode๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

verbose
๋ถ€์šธ

๊ฒฐ๊ณผ ์ •๋ณด์— timing ์ •๋ณด๋ฅผ ํฌํ•จํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. timing ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋ ค๋ฉด verbose๋ฅผ true๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ๊ฐ’์€ false์ž…๋‹ˆ๋‹ค.

MongoDB 4.4๋ถ€ํ„ฐ๋Š” ์ด ์˜ต์…˜์ด ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ ์ •๋ณด์—๋Š” ํ•ญ์ƒ timing ์ •๋ณด๊ฐ€ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. "executionStats" ๋˜๋Š” "allPlansExecution"verbosity ๋ชจ๋“œ์—์„œ db.collection.mapReduce()์™€ ํ•จ๊ป˜ db.collection.explain()์„ ์‹คํ–‰ํ•˜๋ฉด ํƒ€์ด๋ฐ ์ •๋ณด๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

collation
๋ฌธ์„œ

์„ ํƒ ์‚ฌํ•ญ.

์ž‘์—…์— ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ ์ •๋ ฌ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์ •๋ ฌ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋Œ€์†Œ๋ฌธ์ž ๋ฐ ์•…์„ผํŠธ ํ‘œ์‹œ ๊ทœ์น™๊ณผ ๊ฐ™์€ ๋ฌธ์ž์—ด ๋น„๊ต์— ๋Œ€ํ•œ ์–ธ์–ด๋ณ„ ๊ทœ์น™์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์ •๋ ฌ ์˜ต์…˜์˜ ๊ตฌ๋ฌธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

๋ฐ์ดํ„ฐ ์ •๋ ฌ์„ ์ง€์ •ํ•  ๋•Œ locale ํ•„๋“œ๋Š” ํ•„์ˆ˜์ด๊ณ , ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์ •๋ ฌ ํ•„๋“œ๋Š” ๋ชจ๋‘ ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ํ•„๋“œ์— ๋Œ€ํ•œ ์„ค๋ช…์€ ๋ฐ์ดํ„ฐ ์ •๋ ฌ ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๋ฐ์ดํ„ฐ ์ •๋ ฌ์ด ์ง€์ •๋˜์ง€ ์•Š์•˜์ง€๋งŒ ์ปฌ๋ ‰์…˜์— ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ์ •๋ ฌ์ด ์žˆ๋Š” ๊ฒฝ์šฐ( db.createCollection() ์ฐธ์กฐ), ์ž‘์—…์€ ์ปฌ๋ ‰์…˜์— ์ง€์ •๋œ ๋ฐ์ดํ„ฐ ์ •๋ ฌ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ปฌ๋ ‰์…˜ ๋˜๋Š” ์—ฐ์‚ฐ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ์ •๋ ฌ์ด ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ, MongoDB๋Š” ์ด์ „ ๋ฒ„์ „์—์„œ ๋ฌธ์ž์—ด ๋น„๊ต์— ์‚ฌ์šฉ๋œ ๊ฐ„๋‹จํ•œ ์ด์ง„ ๋น„๊ต๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ•œ ์—ฐ์‚ฐ์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ ์ •๋ ฌ์„ ์ง€์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํ•„๋“œ๋ณ„๋กœ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์ •๋ ฌ์„ ์ง€์ •ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ์ •๋ ฌ๊ณผ ํ•จ๊ป˜ ์ฐพ๊ธฐ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ์ฐพ๊ธฐ ์™€ ์ •๋ ฌ์—์„œ ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ์ •๋ ฌ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฒ„์ „ 3.4์— ์ƒˆ๋กœ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

bypassDocumentValidation
๋ถ€์šธ

์„ ํƒ ์‚ฌํ•ญ. mapReduce๊ฐ€ ์ž‘์—… ์ค‘์— ๋ฌธ์„œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜์ง€ ์•Š๋Š” ๋ฌธ์„œ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฒ„์ „ 3.2์— ์ƒˆ๋กœ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ 

map-reduce operations ๋ฐ $where ์—ฐ์‚ฐ์ž ํ‘œํ˜„์‹์€ mongosh์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” db์™€ ๊ฐ™์€ ํŠน์ • ๊ธ€๋กœ๋ฒŒ ํ•จ์ˆ˜ ๋˜๋Š” ์†์„ฑ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

$where ๋ฐ ์—ฐ์‚ฐ์ž map-reduce operations ํ‘œํ˜„์‹์— ๋‹ค์Œ JavaScript ํ•จ์ˆ˜ ๋ฐ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์†์„ฑ
์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ธฐ๋Šฅ
args
MaxKey
MinKey
assert()
BinData()
DBPointer()
DBRef()
doassert()
emit()
gc()
HexData()
hex_md5()
isNumber()
isObject()
ISODate()
isString()
Map()
MD5()
NumberInt()
NumberLong()
ObjectId()
print()
printjson()
printjsononeline()
sleep()
Timestamp()
tojson()
tojsononeline()
tojsonObject()
UUID()
version()

map ํ•จ์ˆ˜๋Š” ๊ฐ ์ž…๋ ฅ ๋ฌธ์„œ๋ฅผ 0๊ฐœ ์ด์ƒ์˜ ๋ฌธ์„œ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. scope ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ •์˜๋œ ๋ณ€์ˆ˜์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ”„๋กœํ† ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค.

function() {
...
emit(key, value);
}

map ํ•จ์ˆ˜์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์š”๊ตฌ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • map ํ•จ์ˆ˜์—์„œ ํ˜„์žฌ ๋ฌธ์„œ๋ฅผ ํ•จ์ˆ˜ ๋‚ด์˜ this๋กœ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

  • map ํ•จ์ˆ˜๋Š” ์–ด๋–ค ์ด์œ ๋กœ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์•ก์„ธ์Šคํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

  • map ํ•จ์ˆ˜๋Š” ์ˆœ์ˆ˜ํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜ ํ•จ์ˆ˜ ์™ธ๋ถ€์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: ๋ถ€์ž‘์šฉ).

  • map ํ•จ์ˆ˜๋Š” ์„ ํƒ์ ์œผ๋กœ emit(key,value)๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•˜์—ฌ key์™€ value๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์ถœ๋ ฅ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ map ํ•จ์ˆ˜๋Š” ์ž…๋ ฅ ๋ฌธ์„œ์˜ status ํ•„๋“œ ๊ฐ’์— ๋”ฐ๋ผ emit(key,value)๋ฅผ 0ํšŒ ๋˜๋Š” 1ํšŒ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

function() {
if (this.status == 'A')
emit(this.cust_id, 1);
}

๋‹ค์Œ map ํ•จ์ˆ˜๋Š” ์ž…๋ ฅ ๋ฌธ์„œ์˜ items ํ•„๋“œ์— ์žˆ๋Š” ์š”์†Œ ์ˆ˜์— ๋”ฐ๋ผ emit(key,value)๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function() {
this.items.forEach(function(item){ emit(item.sku, 1); });
}

reduce ํ•จ์ˆ˜์˜ ํ”„๋กœํ† ํƒ€์ž…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

function(key, values) {
...
return result;
}

reduce ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋™์ž‘์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

  • reduce ํ•จ์ˆ˜๋Š” ์ฝ๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์•ก์„ธ์Šคํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

  • reduce ํ•จ์ˆ˜๋Š” ์™ธ๋ถ€ ์‹œ์Šคํ…œ์— ์˜ํ–ฅ์„ ์ฃผ์–ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

  • MongoDB๋Š” ๋™์ผํ•œ ํ‚ค์— ๋Œ€ํ•ด reduce ํ•จ์ˆ˜๋ฅผ ๋‘ ๋ฒˆ ์ด์ƒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํ•ด๋‹น ํ‚ค์— ๋Œ€ํ•œ reduce ํ•จ์ˆ˜์˜ ์ด์ „ ์ถœ๋ ฅ์€ ํ•ด๋‹น ํ‚ค์— ๋Œ€ํ•œ ๋‹ค์Œ reduce ํ•จ์ˆ˜ ํ˜ธ์ถœ์— ๋Œ€ํ•œ ์ž…๋ ฅ ๊ฐ’ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

  • reduce ํ•จ์ˆ˜๋Š” scope ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ •์˜๋œ ๋ณ€์ˆ˜์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • reduce์— ๋Œ€ํ•œ ์ž…๋ ฅ์€ MongoDB์˜ ์ตœ๋Œ€ BSON ๋ฌธ์„œ ํฌ๊ธฐ ์ ˆ๋ฐ˜๋ณด๋‹ค ํฌ์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํฐ ๋ฌธ์„œ๊ฐ€ ๋ฐ˜ํ™˜๋œ ํ›„ ํ›„์† reduce ๋‹จ๊ณ„์—์„œ ํ•จ๊ป˜ ๊ฒฐํ•ฉ๋˜๋ฉด ์ด ์š”๊ตฌ ์‚ฌํ•ญ์„ ์œ„๋ฐ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋™์ผํ•œ ํ‚ค์— ๋Œ€ํ•ด reduce ํ•จ์ˆ˜๋ฅผ ๋‘ ๋ฒˆ ์ด์ƒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋‹ค์Œ ์†์„ฑ์ด ์ฐธ์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฐ˜ํ™˜ ๊ฐ์ฒด์˜ ์œ ํ˜•์€ map ํ•จ์ˆ˜์—์„œ ๋ฐฉ์ถœํ•œ value์˜ ์œ ํ˜•๊ณผ ๋™์ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • reduce ํ•จ์ˆ˜๋Š” ์—ฐ๊ด€์„ฑ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์„ค๋ช…์ด ์ฐธ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] )
  • reduce ํ•จ์ˆ˜๋Š” ๋ฉฑ๋“ฑ์„ฑ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์„ค๋ช…์ด ์ฐธ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray )
  • reduce ํ•จ์ˆ˜๋Š” ๊ฐ€ํ™˜์ ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, valuesArray ์š”์†Œ์˜ ์ˆœ์„œ๊ฐ€ reduce ํ•จ์ˆ˜์˜ ์ถœ๋ ฅ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์•„์•ผ ํ•˜๋ฏ€๋กœ ๋‹ค์Œ ๋ช…๋ น๋ฌธ์ด ์ฐธ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )

out ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•ด ๋‹ค์Œ ์˜ต์…˜์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์˜ต์…˜์€ ์ƒˆ ์ปฌ๋ ‰์…˜์œผ๋กœ ์ถœ๋ ฅ๋˜๋ฉฐ ๋ณต์ œ๋ณธ ์„ธํŠธ์˜ ์„ธ์ปจ๋”๋ฆฌ ๋…ธ๋“œ์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

out: <collectionName>

์ฐธ๊ณ 

๋ฒ„์ „ 4.2๋ถ€ํ„ฐ MongoDB๋Š” ๋‹ค์Œ์„ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ƒˆ ์ƒค๋“œ ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•˜๋Š” ๋งต ๋ฆฌ๋“€์Šค ์˜ต์…˜์€ ๋ฌผ๋ก  ๋งต ๋ฆฌ๋“€์Šค๋ฅผ ์œ„ํ•œ ์ƒค๋”ฉ ์˜ต์…˜๋„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ƒค๋“œ ์ปฌ๋ ‰์…˜์œผ๋กœ ์ถœ๋ ฅํ•˜๋ ค๋ฉด ๋จผ์ € ์ƒค๋“œ ์ปฌ๋ ‰์…˜์„ ์ƒ์„ฑํ•˜์„ธ์š”. ๊ฒŒ๋‹ค๊ฐ€ MongoDB 4.2๋Š” ๊ธฐ์กด ์ƒค๋“œ ์ปฌ๋ ‰์…˜์˜ ๊ต์ฒด๋ฅผ ๋” ์ด์ƒ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ์˜ต์…˜์€ out์— ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ปฌ๋ ‰์…˜์„ ์ „๋‹ฌํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณต์ œ๋ณธ ์„ธํŠธ์˜ ์„ธ์ปจ๋”๋ฆฌ ๋…ธ๋“œ๋Š” ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

out: { <action>: <collectionName>
[, db: <dbName>]
[, sharded: <boolean> ] }

์ž‘์—…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปฌ๋ ‰์…˜์— ์ถœ๋ ฅํ•˜๋Š” ๊ฒฝ์šฐ out์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • <action>: ๋‹ค์Œ ์ž‘์—… ์ค‘ ํ•˜๋‚˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

    • replace

      <collectionName>์ด ์žˆ๋Š” ์ปฌ๋ ‰์…˜์ด ์žˆ๋Š” ๊ฒฝ์šฐ <collectionName>์˜ ๋‚ด์šฉ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    • merge

      ์ถœ๋ ฅ ์ปฌ๋ ‰์…˜์ด ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ์ƒˆ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์กด ๊ฒฐ๊ณผ์™€ ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๋ฌธ์„œ์— ์ƒˆ ๊ฒฐ๊ณผ์™€ ๋™์ผํ•œ ํ‚ค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ๊ธฐ์กด ๋ฌธ์„œ๋ฅผ ๋ฎ์–ด์”๋‹ˆ๋‹ค.

    • reduce

      ์ถœ๋ ฅ ์ปฌ๋ ‰์…˜์ด ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ์ƒˆ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์กด ๊ฒฐ๊ณผ์™€ ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๋ฌธ์„œ์— ์ƒˆ ๊ฒฐ๊ณผ์™€ ๋™์ผํ•œ ํ‚ค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ƒˆ ๋ฌธ์„œ์™€ ๊ธฐ์กด ๋ฌธ์„œ ๋ชจ๋‘์— reduce ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜๊ณ  ๊ฒฐ๊ณผ๋กœ ๊ธฐ์กด ๋ฌธ์„œ๋ฅผ ๋ฎ์–ด์”๋‹ˆ๋‹ค.

  • db:

    ์„ ํƒ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ๋งต ๋ฆฌ๋“€์Šค ์ž‘์—…์œผ๋กœ ์ถœ๋ ฅ์„ ๊ธฐ๋กํ•  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ž…๋ ฅ ์ปฌ๋ ‰์…˜๊ณผ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋งต ๋ฆฌ๋“€์Šค ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์€ ๋ณต์ œ๋ณธ ์„ธํŠธ์˜ ์„ธ์ปจ๋”๋ฆฌ ๋…ธ๋“œ์—์„œ out์— ๋Œ€ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

out: { inline: 1 }

๊ฒฐ๊ณผ๋Š” BSON ๋ฌธ์„œ์˜ ์ตœ๋Œ€ ํฌ๊ธฐ์— ๋งž์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

finalize ํ•จ์ˆ˜์˜ ํ”„๋กœํ† ํƒ€์ž…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

function(key, reducedValue) {
...
return modifiedObject;
}

finalize ํ•จ์ˆ˜๋Š” ์ธ์ˆ˜๋กœ reduce ํ•จ์ˆ˜์˜ key ๊ฐ’๊ณผ reducedValue๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์‚ฌํ•ญ์— ์œ ์˜ํ•˜์„ธ์š”.

  • finalize ํ•จ์ˆ˜๋Š” ์–ด๋–ค ์ด์œ ๋กœ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์•ก์„ธ์Šคํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

  • finalize ํ•จ์ˆ˜๋Š” ์ˆœ์ˆ˜ํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜ ํ•จ์ˆ˜ ์™ธ๋ถ€์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: ๋ถ€์ž‘์šฉ).

  • finalize ํ•จ์ˆ˜๋Š” scope ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ •์˜๋œ ๋ณ€์ˆ˜์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์„น์…˜์˜ ์˜ˆ์ œ๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์ง‘๊ณ„ ํ‘œํ˜„์‹์ด ์—†๋Š” ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ๋Œ€์•ˆ์„ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค.์‚ฌ์šฉ์ž ์ •์˜ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์•ˆ์— ๋Œ€ํ•ด์„œ๋Š” ๋งต ๋ฆฌ๋“€์Šค์—์„œ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ๋ณ€ํ™˜ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์ด ๋ฌธ์„œ๋กœ ์ƒ˜ํ”Œ ์ปฌ๋ ‰์…˜ orders์„ ๋งŒ๋“œ์„ธ์š”.

db.orders.insertMany([
{ _id: 1, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-01"), price: 25, items: [ { sku: "oranges", qty: 5, price: 2.5 }, { sku: "apples", qty: 5, price: 2.5 } ], status: "A" },
{ _id: 2, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-08"), price: 70, items: [ { sku: "oranges", qty: 8, price: 2.5 }, { sku: "chocolates", qty: 5, price: 10 } ], status: "A" },
{ _id: 3, cust_id: "Busby Bee", ord_date: new Date("2020-03-08"), price: 50, items: [ { sku: "oranges", qty: 10, price: 2.5 }, { sku: "pears", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 4, cust_id: "Busby Bee", ord_date: new Date("2020-03-18"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 5, cust_id: "Busby Bee", ord_date: new Date("2020-03-19"), price: 50, items: [ { sku: "chocolates", qty: 5, price: 10 } ], status: "A"},
{ _id: 6, cust_id: "Cam Elot", ord_date: new Date("2020-03-19"), price: 35, items: [ { sku: "carrots", qty: 10, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 7, cust_id: "Cam Elot", ord_date: new Date("2020-03-20"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 8, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 75, items: [ { sku: "chocolates", qty: 5, price: 10 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 9, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 55, items: [ { sku: "carrots", qty: 5, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 }, { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 10, cust_id: "Don Quis", ord_date: new Date("2020-03-23"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" }
])

orders ์ปฌ๋ ‰์…˜์—์„œ์˜ ๋งต ๋ฆฌ๋“€์Šค ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ cust_id๋ณ„๋กœ ๊ทธ๋ฃนํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ cust_id์— ๋Œ€ํ•œ price์˜ ํ•ฉ๊ณ„๋ฅผ ๊ณ„์‚ฐํ•˜์„ธ์š”.

  1. ๊ฐ ์ž…๋ ฅ ๋ฌธ์„œ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋งต ํ•จ์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ํ•˜์„ธ์š”.

    • ์ด ํ•จ์ˆ˜์—์„œ this๋Š” ๋งต ๋ฆฌ๋“€์Šค ์ž‘์—…์ด ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋Š” ๋ฌธ์„œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    • ์ด ํ•จ์ˆ˜๋Š” ๊ฐ ๋ฌธ์„œ์— ๋Œ€ํ•ด price์„ cust_id์— ๋งคํ•‘ํ•˜๊ณ  cust_id ๋ฐ price์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

    var mapFunction1 = function() {
    emit(this.cust_id, this.price);
    };
  2. ๋‘ ๊ฐœ์˜ ์ธ์ˆ˜ keyCustId์™€ valuesPrices์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์‘ํ•˜๋Š” ๋ฆฌ๋“€์Šค ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์„ธ์š”.

    • valuesPrices๋Š” ๋งต ํ•จ์ˆ˜์—์„œ ๋ฐœ์ƒํ•œ price ๊ฐ’๋“ค๋กœ ๊ตฌ์„ฑ๋œ ๋ฐฐ์—ด์ด๋ฉฐ, ์ด ๊ฐ’๋“ค์€ keyCustId๋กœ ๊ทธ๋ฃนํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

    • ์ด ํ•จ์ˆ˜๋Š” valuesPrice ๋ฐฐ์—ด์„ ํ•ด๋‹น ์š”์†Œ์˜ ํ•ฉ์œผ๋กœ ๋ฆฌ๋“€์Šคํ•ฉ๋‹ˆ๋‹ค.

    var reduceFunction1 = function(keyCustId, valuesPrices) {
    return Array.sum(valuesPrices);
    };
  3. mapFunction1 ๋งต ํ•จ์ˆ˜์™€ reduceFunction1 ๋ฆฌ๋“€์Šค ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ orders ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  ๋ฌธ์„œ์— ๋Œ€ํ•ด ๋งต-๋ฆฌ๋“€์Šค๋ฅผ ์ˆ˜ํ–‰ํ•˜์„ธ์š”.

    db.orders.mapReduce(
    mapFunction1,
    reduceFunction1,
    { out: "map_reduce_example" }
    )

    ์ด ์—ฐ์‚ฐ์€ map_reduce_example์ด๋ผ๋Š” ์ปฌ๋ ‰์…˜์— ํ•ด๋‹น ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. map_reduce_example ์ปฌ๋ ‰์…˜์ด ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ์ด ์—ฐ์‚ฐ์€ ํ•ด๋‹น ์ฝ˜ํ…์ธ ๋ฅผ ์ด ๋งต-๋ฆฌ๋“€์Šค ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

  4. map_reduce_example ์ปฌ๋ ‰์…˜์„ ์ฟผ๋ฆฌํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    db.map_reduce_example.find().sort( { _id: 1 } )

    ์ด ์ž‘์—…์€ ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Busby Bee", "value" : 125 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Don Quis", "value" : 155 }

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ง€์ • ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š๊ณ ๋„ ๋งต-๋ฆฌ๋“€์Šค ์ž‘์—…์„ ๋‹ค์‹œ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

db.orders.aggregate([
{ $group: { _id: "$cust_id", value: { $sum: "$price" } } },
{ $out: "agg_alternative_1" }
])
  1. $group ๋‹จ๊ณ„๋Š” cust_id์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜๊ณ  value ํ•„๋“œ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค ($sum๋„ ์ฐธ์กฐํ•˜์„ธ์š”). value ํ•„๋“œ์—๋Š” ๊ฐ cust_id์˜ ์ด price๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ด ๋‹จ๊ณ„์—์„œ๋Š” ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

    { "_id" : "Don Quis", "value" : 155 }
    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Busby Bee", "value" : 125 }
  2. ๊ทธ๋Ÿฐ ๋‹ค์Œ $out์€ ๊ฒฐ๊ณผ๋ฅผ agg_alternative_1 ์ปฌ๋ ‰์…˜์— ์”๋‹ˆ๋‹ค. $out ๋Œ€์‹  $merge๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  3. agg_alternative_1 ์ปฌ๋ ‰์…˜์„ ์ฟผ๋ฆฌํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    db.agg_alternative_1.find().sort( { _id: 1 } )

    ์ด ์ž‘์—…์€ ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Busby Bee", "value" : 125 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Don Quis", "value" : 155 }

ํŒ

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

์‚ฌ์šฉ์ž ์ •์˜ ์ง‘๊ณ„ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์•ˆ์€ ๋งต-๋ฆฌ๋“€์Šค์—์„œ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ๋ณ€ํ™˜ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๋‹ค์Œ ์˜ˆ์ œ์—์„œ๋Š” ord_date ๊ฐ’์ด 2020-03-01 ์ด์ƒ์ธ ๋ชจ๋“  ๋ฌธ์„œ์— ๋Œ€ํ•œ orders ์ปฌ๋ ‰์…˜์—์„œ์˜ ๋Œ€ํ•œ ๋งต-๋ฆฌ๋“€์Šค ์—ฐ์‚ฐ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ์˜ˆ์ œ์—์„œ์˜ ์—ฐ์‚ฐ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. item.sku ํ•„๋“œ๋ณ„๋กœ ๊ทธ๋ฃนํ™”ํ•˜๊ณ  ๊ฐ sku์— ๋Œ€ํ•ด ์ฃผ๋ฌธ ์ˆ˜์™€ ์ด ์ฃผ๋ฌธ ์ˆ˜๋Ÿ‰์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

  2. ๊ฐ sku ๊ฐ’์— ๋Œ€ํ•œ ์ฃผ๋ฌธ๋‹น ํ‰๊ท  ์ˆ˜๋Ÿ‰์„ ๊ณ„์‚ฐํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅ ์ปฌ๋ ‰์…˜์— ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

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

์˜ˆ์‹œ ๋‹จ๊ณ„:

  1. ๊ฐ ์ž…๋ ฅ ๋ฌธ์„œ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋งต ํ•จ์ˆ˜๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ํ•˜์„ธ์š”.

    • ์ด ํ•จ์ˆ˜์—์„œ this๋Š” ๋งต ๋ฆฌ๋“€์Šค ์ž‘์—…์ด ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋Š” ๋ฌธ์„œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    • ํ•จ์ˆ˜๋Š” ๊ฐ ํ•ญ๋ชฉ์— ๋Œ€ํ•ด sku๋ฅผ ์ƒˆ๋กœ์šด value ๊ฐ์ฒด์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ์ฒด์—๋Š” count ๊ฐ’ 1๊ณผ ์ฃผ๋ฌธ์— ๋Œ€ํ•œ ํ•ญ๋ชฉ qty๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ, sku (key ์— ์ €์žฅ๋จ)์™€ value๋ฅผ ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค.

    var mapFunction2 = function() {
    for (var idx = 0; idx < this.items.length; idx++) {
    var key = this.items[idx].sku;
    var value = { count: 1, qty: this.items[idx].qty };
    emit(key, value);
    }
    };
  2. ๋‘ ๊ฐœ์˜ ์ธ์ˆ˜ keySKU์™€ countObjVals์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์‘ํ•˜๋Š” ๋ฆฌ๋“€์Šค ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์„ธ์š”.

    • countObjVals ๋งต ํ•จ์ˆ˜๊ฐ€ ๋ฆฌ๋“€์„œ ํ•จ์ˆ˜์— ์ „๋‹ฌํ•œ ๊ทธ๋ฃนํ™”๋œ keySKU ๊ฐ’์— ๋งคํ•‘๋œ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค.

    • ์ด ํ•จ์ˆ˜๋Š” countObjVals ๋ฐฐ์—ด์„ count ๋ฐ qty ํ•„๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋‹จ์ผ ๊ฐ์ฒด reducedValue๋กœ ์ค„์ž…๋‹ˆ๋‹ค.

    • reducedVal ์—์„œ count ํ•„๋“œ๋Š” ๊ฐœ๋ณ„ ๋ฐฐ์—ด ์š”์†Œ์˜ count ํ•„๋“œ ํ•ฉ๊ณ„๋ฅผ ํฌํ•จํ•˜๊ณ  qty ํ•„๋“œ๋Š” ๊ฐœ๋ณ„ ๋ฐฐ์—ด ์š”์†Œ์˜ qty ํ•„๋“œ ํ•ฉ๊ณ„๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

    var reduceFunction2 = function(keySKU, countObjVals) {
    reducedVal = { count: 0, qty: 0 };
    for (var idx = 0; idx < countObjVals.length; idx++) {
    reducedVal.count += countObjVals[idx].count;
    reducedVal.qty += countObjVals[idx].qty;
    }
    return reducedVal;
    };
  3. ๋‘ ๊ฐœ์˜ ์ธ์ˆ˜ key์™€ reducedVal์„ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ข… ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” reducedVal ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ avg๋ผ๋Š” ๊ณ„์‚ฐ๋œ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ˆ˜์ •๋œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

    var finalizeFunction2 = function (key, reducedVal) {
    reducedVal.avg = reducedVal.qty/reducedVal.count;
    return reducedVal;
    };
  4. mapFunction2, reduceFunction2 ๋ฐ finalizeFunction2 ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ orders ์ปฌ๋ ‰์…˜์— ๋Œ€ํ•ด ๋งต-๋ฆฌ๋“€์Šค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”.

    db.orders.mapReduce(
    mapFunction2,
    reduceFunction2,
    {
    out: { merge: "map_reduce_example2" },
    query: { ord_date: { $gte: new Date("2020-03-01") } },
    finalize: finalizeFunction2
    }
    );

    ์ด ์ž‘์—…์€ query ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ord_date๊ฐ€ new Date("2020-03-01") ์ด์ƒ์ธ ๋ฌธ์„œ๋งŒ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฒฐ๊ณผ๋ฅผ ์ปฌ๋ ‰์…˜ map_reduce_example2์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

    map_reduce_example2 ์ปฌ๋ ‰์…˜์ด ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ์ž‘์—…์€ ๊ธฐ์กด ์ฝ˜ํ…์ธ ๋ฅผ ์ด ๋งต-๋ฆฌ๋“€์Šค ์—ฐ์‚ฐ์˜ ๊ฒฐ๊ณผ์™€ ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๊ธฐ์กด ๋ฌธ์„œ์— ์ƒˆ ๊ฒฐ๊ณผ์™€ ๋™์ผํ•œ ํ‚ค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์—ฐ์‚ฐ์€ ๊ธฐ์กด ๋ฌธ์„œ๋ฅผ ๋ฎ์–ด์”๋‹ˆ๋‹ค. ๋™์ผํ•œ ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ธฐ์กด ๋ฌธ์„œ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ๋ฌธ์„œ๊ฐ€ ์‚ฝ์ž…๋ฉ๋‹ˆ๋‹ค.

  5. map_reduce_example2 ์ปฌ๋ ‰์…˜์„ ์ฟผ๋ฆฌํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    db.map_reduce_example2.find().sort( { _id: 1 } )

    ์ด ์ž‘์—…์€ ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ง€์ • ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š๊ณ ๋„ ๋งต-๋ฆฌ๋“€์Šค ์ž‘์—…์„ ๋‹ค์‹œ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

db.orders.aggregate( [
{ $match: { ord_date: { $gte: new Date("2020-03-01") } } },
{ $unwind: "$items" },
{ $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } } },
{ $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },
{ $merge: { into: "agg_alternative_3", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }
] )
  1. $match ๋‹จ๊ณ„์—์„œ๋Š” ord_date๊ฐ€ new Date("2020-03-01") ์ด์ƒ์ธ ๋ฌธ์„œ๋งŒ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  2. $unwind ๋‹จ๊ณ„์—์„œ๋Š” items ๋ฐฐ์—ด ํ•„๋“œ๋ณ„๋กœ ๋ฌธ์„œ๋ฅผ ์„ธ๋ถ„ํ™”ํ•˜์—ฌ ๊ฐ ๋ฐฐ์—ด ์š”์†Œ์— ๋Œ€ํ•œ ๋ฌธ์„œ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    ...
  3. $group ๋‹จ๊ณ„๋Š” items.sku๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜์—ฌ ๊ฐ sku์— ๋Œ€ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

    • qty ํ•„๋“œ. qty ํ•„๋“œ๋Š” ๋‹ค์Œ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
      ๊ฐ items.sku์— ๋Œ€ํ•œ ์ด qty ($sum ์ฐธ์กฐ).
    • orders_ids ๋ฐฐ์—ด. orders_ids ํ•„๋“œ๋Š” ๋‹ค์Œ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
      items.sku์— ๋Œ€ํ•œ ๊ณ ์œ  ์ฃผ๋ฌธ _id ๋ฐฐ์—ด ($addToSet์ฐธ์กฐ).
    { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] }
    { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] }
    { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
    { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] }
    { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }
  4. $project ๋‹จ๊ณ„์—์„œ๋Š” ๋งต ๋ฆฌ๋“€์Šค์˜ ์ถœ๋ ฅ์„ ๋ฏธ๋Ÿฌ๋งํ•˜์—ฌ _id์™€ value ๋‘ ํ•„๋“œ๋ฅผ ๊ฐ–๋„๋ก ์ถœ๋ ฅ ๋ฌธ์„œ๋ฅผ ์žฌ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. $project๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  5. $unwind ๋‹จ๊ณ„์—์„œ๋Š” items ๋ฐฐ์—ด ํ•„๋“œ๋ณ„๋กœ ๋ฌธ์„œ๋ฅผ ์„ธ๋ถ„ํ™”ํ•˜์—ฌ ๊ฐ ๋ฐฐ์—ด ์š”์†Œ์— ๋Œ€ํ•œ ๋ฌธ์„œ๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    ...
  6. $group ๋‹จ๊ณ„๋Š” items.sku๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜์—ฌ ๊ฐ sku์— ๋Œ€ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

    • qty ํ•„๋“œ.qty ํ•„๋“œ์—๋Š” $sum์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์‚ฐ๋œ ๊ฐ items.sku ๋ณ„ ์ฃผ๋ฌธ๋œ ์ด qty๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

    • orders_ids ๋ฐฐ์—ด. orders_ids ํ•„๋“œ๋Š” $addToSet์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์‚ฐ๋œ items.sku์˜ ๊ณ ์œ ํ•œ ์ฃผ๋ฌธ _id ๋ฐฐ์—ด์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

    { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] }
    { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] }
    { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
    { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] }
    { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }
  7. $project ๋‹จ๊ณ„์—์„œ๋Š” ๋งต ๋ฆฌ๋“€์Šค์˜ ์ถœ๋ ฅ์„ ๋ฏธ๋Ÿฌ๋งํ•˜์—ฌ _id์™€ value ๋‘ ํ•„๋“œ๋ฅผ ๊ฐ–๋„๋ก ์ถœ๋ ฅ ๋ฌธ์„œ๋ฅผ ์žฌ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. $project๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    • $size ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ value.count๋ฅผ orders_ids ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    • value.qty๋ฅผ ์ž…๋ ฅ ๋ฌธ์„œ์˜ qty ํ•„๋“œ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    • $divide์™€ $size๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ value.avg๋ฅผ ์ฃผ๋ฌธ๋‹น ํ‰๊ท  ์ฃผ๋ฌธ ์ˆ˜๋Ÿ‰์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
  8. ๋งˆ์ง€๋ง‰์œผ๋กœ $merge๋Š” ์ถœ๋ ฅ์„ ์ปฌ๋ ‰์…˜ agg_alternative_3์— ์”๋‹ˆ๋‹ค. ๊ธฐ์กด ๋ฌธ์„œ์— ์ƒˆ ๊ฒฐ๊ณผ์™€ ๋™์ผํ•œ ํ‚ค _id๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ž‘์—…์€ ๊ธฐ์กด ๋ฌธ์„œ๋ฅผ ๋ฎ์–ด์”๋‹ˆ๋‹ค. ๋™์ผํ•œ ํ‚ค๋ฅผ ๊ฐ€์ง„ ๊ธฐ์กด ๋ฌธ์„œ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์ž‘์—…์ด ๋ฌธ์„œ๋ฅผ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค.

  9. agg_alternative_3 ์ปฌ๋ ‰์…˜์„ ์ฟผ๋ฆฌํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    db.agg_alternative_3.find().sort( { _id: 1 } )

    ์ด ์ž‘์—…์€ ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }

ํŒ

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

์‚ฌ์šฉ์ž ์ •์˜ ์ง‘๊ณ„ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์•ˆ์€ ๋งต-๋ฆฌ๋“€์Šค์—์„œ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ๋ณ€ํ™˜ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

db.collection.mapReduce() ๋ฉ”์„œ๋“œ์˜ ์ถœ๋ ฅ์€ mapReduce ๋ช…๋ น์˜ ์ถœ๋ ฅ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ์ถœ๋ ฅ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ mapReduce ๋ช…๋ น์˜ ์ถœ๋ ฅ db.collection.mapReduce() ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”.

db.collection.mapReduce()๋Š” ๋” ์ด์ƒ afterClusterTime์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ db.collection.mapReduce()๋Š” ์ธ๊ณผ์ ์œผ๋กœ ์ผ๊ด€๋œ ์„ธ์…˜๊ณผ ์—ฐ๊ฒฐ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋Œ์•„๊ฐ€๊ธฐ

db.collection.latencyStats()

๋‹ค์Œ

db.collection.reIndex()