기본 구조
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intent" : "MBTI_TYPE",
"intentArray" : [
{
"type1" : "ISTJ",
"executeInfo" : [
{
"check" : "foodTendency",
"type2" : "female",
"type2Data" : [
{
"searchData" : {
"name" : "Jessica",
"height" : "165",
"weight" : "42"
},
"returnData" : "파인애플"
},
{
"searchData" : {
"name" : "Amy",
"height" : "165",
"weight" : "42"
},
"returnData" : "사과"
},
{
"searchData" : {
"name" : "Alice",
"height" : "165",
"weight" : "42"
},
"returnData" : "샌드위치"
}
]
},
{
"check" : "foodTendency",
"type2" : "male",
"type2Data" : [
{
"searchData" : {
"name" : "john",
"height" : "175",
"weight" : "72"
},
"returnData" : "파인애플"
},
{
"searchData" : {
"name" : "josh",
"height" : "190",
"weight" : "92"
},
"returnData" : "사과"
},
{
"searchData" : {
"name" : "kan",
"height" : "185",
"weight" : "82"
},
"returnData" : "샌드위치"
}
]
}
]
}
]
}
aggregate는 일단 배열 형태로 조회를 한다.
따라서
db.getCollection('콜렉션 명').aggregate([ {} ]);
이런한 형태로 조회를 하고
$match
$unwind
$group
$push
$addToSet
$in
$elemMatch
...
등등 다양한 연산자를 갖췄다.
이를 기반으로 다양한 함수를 써보자.
$match를 쓰면 특정 필드의 값이 들어간 도큐먼트 조회를 할 수 있다.
db.getCollection('intent_test').aggregate([
{$match :{"intent" : "MBTI_TYPE"}}
]);
/* 1 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intent" : "MBTI_TYPE",
"intentArray" : [
{
"type1" : "ISTJ",
"executeInfo" : [
{
"check" : "foodTendency",
"type2" : "female",
"type2Data" : [
{
"searchData" : {
"name" : "Jessica",
"height" : "165",
"weight" : "42"
},
"returnData" : "파인애플"
},
{
"searchData" : {
"name" : "Amy",
"height" : "165",
"weight" : "42"
},
"returnData" : "사과"
},
{
"searchData" : {
"name" : "Alice",
"height" : "165",
"weight" : "42"
},
"returnData" : "샌드위치"
}
]
},
{
"check" : "foodTendency",
"type2" : "male",
"type2Data" : [
{
"searchData" : {
"name" : "john",
"height" : "175",
"weight" : "72"
},
"returnData" : "파인애플"
},
{
"searchData" : {
"name" : "josh",
"height" : "190",
"weight" : "92"
},
"returnData" : "사과"
},
{
"searchData" : {
"name" : "kan",
"height" : "185",
"weight" : "82"
},
"returnData" : "샌드위치"
}
]
}
]
}
]
}
하지만 나아가 특정 필드의 값만 조회하고 싶은 경우
예를들어
type2의 값이 male이고 name이 john의 returnData 값을 조회하고 싶다면
어떻게 할까?
이경우에는 $unwind를 써야 한다.
db.getCollection('intent_test').aggregate([
{$match :{"intent" : "MBTI_TYPE"}},
{$unwind : "$intentArray"},
{$unwind : "$intentArray.executeInfo"}
]);
결과
/* 1 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intent" : "MBTI_TYPE",
"intentArray" : {
"type1" : "ISTJ",
"executeInfo" : {
"check" : "foodTendency",
"type2" : "female",
"type2Data" : [
{
"searchData" : {
"name" : "Jessica",
"height" : "165",
"weight" : "42"
},
"returnData" : "파인애플"
},
{
"searchData" : {
"name" : "Amy",
"height" : "165",
"weight" : "42"
},
"returnData" : "사과"
},
{
"searchData" : {
"name" : "Alice",
"height" : "165",
"weight" : "42"
},
"returnData" : "샌드위치"
}
]
}
}
}
/* 2 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intent" : "MBTI_TYPE",
"intentArray" : {
"type1" : "ISTJ",
"executeInfo" : {
"check" : "foodTendency",
"type2" : "male",
"type2Data" : [
{
"searchData" : {
"name" : "john",
"height" : "175",
"weight" : "72"
},
"returnData" : "파인애플"
},
{
"searchData" : {
"name" : "josh",
"height" : "190",
"weight" : "92"
},
"returnData" : "사과"
},
{
"searchData" : {
"name" : "kan",
"height" : "185",
"weight" : "82"
},
"returnData" : "샌드위치"
}
]
}
}
}
결과 값을 잘 살펴보면 _id값이 두개가 생겼다. 즉 하나의 document가 document 두개로 나뉘어진 것을 알 수 있다.
document 단위로 조회되는 몽고디비는 $unwind를 사용했을 때 좀 더 자세하게 조회는 물론 좀 더 구체적인 특정 값만
뽑을 수 있게 된다.
자 이제
type2의 값이 male이고 name이 john의 returnData 값을 조회해보자.
db.getCollection('intent_test').aggregate([
{$match :{"intent" : "MBTI_TYPE"}},
{$unwind : "$intentArray"},
{$unwind : "$intentArray.executeInfo"},
{$unwind : "$intentArray.executeInfo.type2Data"},
{$match :{"intentArray.executeInfo.type2Data.searchData.name" : "john"}},
]);
결과
/* 1 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intent" : "MBTI_TYPE",
"intentArray" : {
"type1" : "ISTJ",
"executeInfo" : {
"check" : "foodTendency",
"type2" : "male",
"type2Data" : {
"searchData" : {
"name" : "john",
"height" : "175",
"weight" : "72"
},
"returnData" : "파인애플"
}
}
}
}
앞선 말한 조건의 해당 값만 document로 조회되었다.
근데 우리는 returnData의 값 파인애플만 필요하다.
이때는 어떻게 해야할까?
그러면
$project를 쓰면 된다.
db.getCollection('intent_test').aggregate([
{$match :{"intent" : "MBTI_TYPE"}},
{$unwind : "$intentArray"},
{$unwind : "$intentArray.executeInfo"},
{$unwind : "$intentArray.executeInfo.type2Data"},
{$match :{"intentArray.executeInfo.type2Data.searchData.name" : "john"}},
{$project : {_id: '$_id', "intentArray.executeInfo.type2Data.returnData": 1}},
]);
결과
/* 1 */
{
"intentArray" : {
"executeInfo" : {
"type2Data" : {
"returnData" : "파인애플"
}
}
},
"_id" : ObjectId("5edf2e8ec4130e33cda725b3")
}
끝.
$sample
이번에는 $sample 연산자를 알아보자
특정 Array에서 특정 객체를 랜덤으로 조회하고 싶을 때 쓴다.
type2Data 안의 특정 사람의 신체 특성 그리고 그에 해당하는 returnData값을
객체 형태로 랜덤 식으로 2개씩 뽑는 것이다.
db.getCollection('intent_test').aggregate([
{$match :{"intent" : "MBTI_TYPE"}},
{$unwind : "$intentArray"},
{$unwind : "$intentArray.executeInfo"},
{$unwind : "$intentArray.executeInfo.type2Data"},
{$sample : {size : 2}}
]);
결과
/* 1 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intent" : "MBTI_TYPE",
"intentArray" : {
"type1" : "ISTJ",
"executeInfo" : {
"check" : "foodTendency",
"type2" : "female",
"type2Data" : {
"searchData" : {
"name" : "Alice",
"height" : "165",
"weight" : "42"
},
"returnData" : "샌드위치"
}
}
}
}
/* 2 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intent" : "MBTI_TYPE",
"intentArray" : {
"type1" : "ISTJ",
"executeInfo" : {
"check" : "foodTendency",
"type2" : "female",
"type2Data" : {
"searchData" : {
"name" : "Amy",
"height" : "165",
"weight" : "42"
},
"returnData" : "사과"
}
}
}
}
이번에는 $unwind로 나뉘어진 document를 다시 하나의 document로 만드는 방법
정확히는 나뉘어진 Array를 하나의 Array로 합치는 것이다.
$push
db.getCollection('intent_test').aggregate([
{$match :{"intent" : "MBTI_TYPE"}},
{$unwind : "$intentArray"},
{$unwind : "$intentArray.executeInfo"},
{$unwind : "$intentArray.executeInfo.type2Data"},
{$sample : {size : 2}},
{$group : {'_id' : '$_id', "type2Data" : {$push : "$intentArray.executeInfo.type2Data"}}}
]);
결과
/* 1 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"type2Data" : [
{
"searchData" : {
"name" : "Amy",
"height" : "165",
"weight" : "42"
},
"returnData" : "사과"
},
{
"searchData" : {
"name" : "josh",
"height" : "190",
"weight" : "92"
},
"returnData" : "사과"
}
]
}
근데 특정 값만 나오고 다른 필드가 사라진 것을 알 수 있다.
이유는 $group 연산자에서 특정 필드만 group했기 때문이다.
이렇게 $push의 Array 형태를 좀 더 크게 설정하면 원하는 결과를 만들 수 있다.
db.getCollection('intent_test').aggregate([
{$match :{"intent" : "MBTI_TYPE"}},
{$unwind : "$intentArray"},
{$unwind : "$intentArray.executeInfo"},
{$unwind : "$intentArray.executeInfo.type2Data"},
{$sample : {size : 2}},
{$group : {'_id' : '$_id', "intentArray" : { $push : "$intentArray"}}}
]);
결과
/* 1 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intentArray" : [
{
"type1" : "ISTJ",
"executeInfo" : {
"check" : "foodTendency",
"type2" : "male",
"type2Data" : {
"searchData" : {
"name" : "kan",
"height" : "185",
"weight" : "82"
},
"returnData" : "샌드위치"
}
}
},
{
"type1" : "ISTJ",
"executeInfo" : {
"check" : "foodTendency",
"type2" : "male",
"type2Data" : {
"searchData" : {
"name" : "josh",
"height" : "190",
"weight" : "92"
},
"returnData" : "사과"
}
}
}
]
}
자 이제 여러 연산자를 조합해서 좀더 의미있는 데이터를 조회해보자.
이 때 연산자의 순서 즉 위치가 중요하다.
type2 필드의 내림차순으로 0번째 값부터 조회하고 값은 1개로 제한
db.getCollection('intent_test').aggregate([
{$match :{"intent" : "MBTI_TYPE"}},
{$unwind : "$intentArray"},
{$unwind : "$intentArray.executeInfo"},
{$sort : {"intentArray.executeInfo.type2" : -1}},
{$skip : 0},
{$limit : 1}
]);
결과
/* 1 */
{
"_id" : ObjectId("5edf2e8ec4130e33cda725b3"),
"intent" : "MBTI_TYPE",
"intentArray" : {
"type1" : "ISTJ",
"executeInfo" : {
"check" : "foodTendency",
"type2" : "male",
"type2Data" : [
{
"searchData" : {
"name" : "john",
"height" : "175",
"weight" : "72"
},
"returnData" : "파인애플"
},
{
"searchData" : {
"name" : "josh",
"height" : "190",
"weight" : "92"
},
"returnData" : "사과"
},
{
"searchData" : {
"name" : "kan",
"height" : "185",
"weight" : "82"
},
"returnData" : "샌드위치"
}
]
}
}
}
'IT > MongoDB' 카테고리의 다른 글
JSON.parse() 활용하여 몽고디비 필드 동적 생성 (0) | 2021.04.11 |
---|---|
몽고디비 - findOneAndUpdate (0) | 2020.06.13 |
MONGODB - find (0) | 2020.06.13 |
MONGODB - 기본구조 (0) | 2020.06.09 |
몽고DB 집계 함수 (0) | 2019.07.30 |