mongoDB + Postman + vue

국비 코딩 풀스택 수업 23일차 (최고 난이도 데이터 차트 만들기)

비루블 2022. 7. 22. 12:33

https://www.chartjs.org/docs/latest/charts/line.html

 

Line Chart | Chart.js

Line Chart A line chart is a way of plotting data points on a line. Often, it is used to show trend data, or the comparison of two data sets. const config = { type: 'line', data: data, };const config = { type: 'line', data: data, }; const labels = Utils.mo

www.chartjs.org

요약정리

오전

고객용 주문목록, 판매자의 본인 물품 가져오기

이거 하는데 여러 erd에서 정보를 받아오느라 배열이 꼬이기 시작해서 이해하기 어려웠긴함.

하지만 이해하면 실력이 향상될지도?

 

오후

SellerOrder.vue만듬

차트를 만들었음

CMD> npm install chart.js @j-t-mcc/vue3-chartjs

v-if 와 v-show 의 차이점

v-if 숨기고 누르면 만드는 것이라서 handleData2가 onMounted에 있기때문에 충동오류가 떳었음.

v-show가 오류가 나지 않았던 것은 handelData2를 실행시켜놓고 차트를 만들어놓고 숨겼기때문

(hidden으로 만들어 놓는 것이라함.)

 

 

 

 

오전일과 
get selectlist 중요중요중요중요중요중요중요중요중요중요

//고객용 주문목록
// 127.0.0.1:3000/order/selectlist.json
// 로그인 고객의 토큰
// result 주문정보만 불러옴(주문정보)
// result1 얘는 Item에서 아이템 정보를 불러옴.
router.get('/selectlist.json', auth.checkToken, 
    async function(req, res, next) {
    try {
        const memberid = req.body.SID;
        //{DB의 컬럼명 : 실제값이 보관된 변수명}
        const query    = {memberid : memberid};

        const result   = await Order.find(query);
        console.log(result);
        for(let i = 0; i<result.length; i++){
            //위치정보를 이용한 탐색
            //console.log(result[i].itemcode);
        }
        console.log("--------------------------");
        let arr = []; // result, result1을 합치기 위한 변수
        for(let tmp of result){ //
            // console.log(tmp.itemcode);

            const result1 = await Item.findOne( {_id : tmp.itemcode} );
            console.log(result1);

            arr.push({orderInfo : tmp, itemInfo : result1})
        }
        
        return res.send( {status : 200, result : arr} );
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

 

고객용 주문목록
중요
result 주문정보만 불러옴(주문정보)
result1 얘는 Item에서 아이템 정보를 불러옴.

합치기 arr

형태 사진 참고~~~

 




get groupitem

// 판매자용 물품별 주문내역
// 127.0.0.1:3000/order/groupitem.json
// 로그인한 판매자의 토큰
// 판매자의 토큰으로 판매자의 물품번호를 싸악 들고오고
// 물품 코드들로 주문내역을 싸악 들고오고
// 들고온 정보를 토대로(memberid)
// 고객의 정보를 싸악들고오고

// 이거 보니까 order.js가 
// 지금까지 배운 것 중 난이도 최상 중요중요중요중요중요중요중요
// 아주아주 중요중요중요중요중요중요중요중요중요중요중요중요중요중요

// result3하는데 중요중요중요중요중요중요중요중요중요중요중요중요
// 난이도 초초초최최상상상
// 물품별 수량, 합계
// 통계를 함 aggregate(어렵지만 그룹을 할 수 있다는 장점)
// 백엔드 orders에서 가져오는 작업

// aggregate
// 어디서 들고올지 (조건임)
// 뭘 들고올지 (필요한 것만)
// 어떤걸 그룹할지 (그룹 조건, (물품코드별 그룹, 개수별, 합계, 평균))
// 정렬방법
router.get('/groupitem.json', auth.checkToken1, async function(req, res, next) {
    try {
        //토큰에서 판매자 본인의 물품을 다 가져오는게 첫순서
        const sellerid = req.body.SID;

        // 현재로그인한 판매자의 판매물품번호 가져오기
        const result = await Item.find({seller : sellerid})
                        .select({ _id : 1 });



        // 물품 코드들로 주문내역을 싸악 들고오고

        // result => [ { _id: 7 }, { _id: 8 }, { _id: 9 }, { _id: 10 } ]
        // query  => [ 7, 8, 9, 10 ]
        // $in에 위에 있는 query같은 형태로 만들어서 넣어줘야해서
        // arr을 만들고 반복문으로 배열을 만들어줌 중요중요중요중요중요중요
        console.log('result => ', result);

        let arr = [];
        for(let tmp of result) { 
            arr.push( tmp._id );
        }
        console.log('arr => ', arr);

        const query = { itemcode : { $in : arr } }
        const result1 = await Order.find(query);
        console.log('result1 => ', result1);


        // 들고온 정보(주문내역)를 토대로(memberid를 이용하여)  고객정보 들고오기
        let arr1 = [];
        for(let tmp of result1) {
            const result2 = await Member
                .findOne({_id : tmp.memberid})
                .select({password:0, regdate:0, role:0});
            console.log('result2 => ', result2);
            arr1.push({ orderInfo: tmp, memberInfo : result2  });
        }


        // 이건 그룹으로 통계 내어보기
        // 그룹 => 물품별 수량, 합계, 
        const result3 = await Order.aggregate([
            {
                $match : { // 조건(어디서 들고올지)
                    itemcode : {
                        $in : arr
                    }
                }
            },
            {
                $project : { // 뭘 들고올지(필요한 것만)
                    cnt : 1,
                    itemcode:1,
                }
            },
            {
                $group : { //그룹조건
                    _id   : '$itemcode',//물품코드별 그룹
                    count : {$sum : 1}, // 물품개수별
                    total : {$sum : '$cnt'}, // 합계별
                    avg   : {$avg : '$cnt'}, // 평균(주문수량/주문횟수)
                }
            },
            {
                $sort : {
                    _id : 1
                }
            }
        ]);

        console.log('result3 => ', result3)

        return res.send( {status : 200, result:arr1, result3:result3} );
    }
    catch(e){
        console.error(e);
        return res.send( {status:-1, result:e} );
    }
});


토큰에서 판매자 본인의 물품을 다 가져오는게 첫순서
$in 을 배움 중요중요중요중요중요중요중요중요중요중요중요중요중요중요

$in은 몽고디비 언어기때문에, 정해진 형태로 넣어줘야해서 arr를 활용해서 데이터 배열을 다시 만들어준 뒤 넣어줌배열바꾸기 중요중요중요중요중요중요중요중요중요중요중요중요


해당 코드의 목적 : 어떤사람이 주문했고, 어디로 보내야하는지(여기는 그냥 회원정보만) 보는 것

아래는 해당 코드의 원리

판매자의 토큰으로 판매자의 물품번호를 싸악 들고오고
물품 코드들로 주문내역을 싸악 들고오고
들고온 정보를 토대로(memberid)
고객의 정보를 싸악들고오고

이거 보니까 order.js가 
지금까지 배운 것 중 난이도 최상

이것만 잘 이해해도 지금까지 배운 것들은 쉽게 코드를 짤 수 있을것 같은 느낌
아주아주 중요중요중요중요중요중요중요중요중요중요중요중요중요중요

result3하는데 중요중요중요중요중요중요중요중요중요중요중요중요
난이도 초초초최최상상상
물품별 수량, 합계
통계를 함 aggregate(어렵지만 그룹을 할 수 있다는 장점)
백엔드 orders에서 가져오는 작업
---------------------------------------------
어디서 들고올지 (조건임)
뭘 들고올지 (필요한 것만)
어떤걸 그룹할지 (그룹 조건, (물품코드별 그룹, 개수별, 합계, 평균))
정렬방법
---------------------------------------------
$in은 몽고디비쪽언어

get groupmember
판매자용 고객별 주문내역 중요중요중요중요중요중요중요중요중요

// 판매자용 고객별 주문내역
// 127.0.0.1:3000/order/groupmember.json
// 로그인한 판매자의 토큰

//aggregate 한번 더 사용
//조건, 들고올 항목, 어떤걸 그룹할지, 차순
//그리고 들고온 정보들을 arr과 for문을 이용하여 하나의 정보에 담고 출력시켜줌
//하나의 정보에 담는 부분 어렵지만, 이해하면 굉장히 좋을듯
router.get('/groupmember.json', auth.checkToken1, async function(req, res, next) {
    try {
        const sellerid = req.body.SID;

        // 현재로그인한 판매자의 판매물품번호 가져오기
        const result = await Item.find({seller : sellerid})
                        .select({ _id : 1 });

        let arr = [];
        for(let tmp of result) { 
            arr.push( tmp._id );
        }
        // result => [ { _id: 7 }, { _id: 8 }, { _id: 9 }, { _id: 10 } ]
        // arr    => [ 7, 8, 9, 10 ]
        console.log('arr => ', arr);
        
        const result1 = await Order.aggregate([
            {
                $match : { // 조건(어디서 들고올지)
                    itemcode : {
                        $in : arr
                    }
                }
            },
            {
                $project : { // 가져올 항목 프로젝션
                    cnt      : 1,
                    memberid : 1
                }
            },
            {
                $group : { // 위의 프로젝션에 있는 컬럼명 명시
                    _id   : '$memberid',
                    count : {$sum : 1},
                    total : {$sum : '$cnt'},
                    avg   : {$avg : '$cnt'},
                    max   : {$max : '$cnt'}

                }
            },
            {
                $sort : { // 정렬조건 그룹했던 항목 _id기준 내림차
                    _id : -1
                }
            }
        ]);

        //그리고 들고온 정보들을 arr과 for문을 이용하여 하나의 정보에 담고 출력시켜줌
        //하나의 정보에 담는 부분 어렵지만, 이해하면 굉장히 좋을듯
        let arr2 = [];
        for(let tmp of result1) {
            const result2 = await Member
                .findOne({_id : tmp._id})
                .select({password:0});
            arr2.push({ orderInfo: tmp, memberInfo : result2  });
        }
        console.log(arr2);


        return res.send( {status:200, result:arr2} );
    }
    
    catch(e){
        console.error(e);
        return res.send( {status:-1, result:e} );
    }
});

--------aggregate사용법--------
조건
들고올 항목만
어떤걸 그룹할지
차순
--------------------------------------
여기서 이제 그룹결과 + 회원정보포함해서 리턴
이거 배열에 넣는 부분 좀 어렵지만 이해하면 정말 도움 많이 될듯.


 

오후일과

SellerOrder.vue만듬

import Vue3ChartJs from '@j-t-mcc/vue3-chartjs'

 

<template>
    <div>
        <h3>주문관리</h3>
        <hr/>

        <button @click="state.menu=1">물품별</button>
        <button @click="state.menu=2">회원별</button>

        <div v-show="state.menu===1">
            <h4>물품별 주문내역</h4>
            <table border="1">
                <tr>
                    <th>주문번호</th>
                    <th>주문수량</th>
                    <th>물품번호</th>
                    <th>회원아이디</th>
                    <th>회원이름</th>
                    <th>회원이메일</th>
                    <th>회원연락처</th>
                </tr>
                <tr v-for="tmp of state.rows" :key="tmp">
                    <td>{{tmp.orderInfo._id}}</td>
                    <td>{{tmp.orderInfo.cnt}}</td>
                    
                    <td style="cursor: pointer; color: blue;"
                    @click="handleContent(tmp.orderInfo.itemcode)">{{tmp.orderInfo.itemcode}}</td>
                    <td>{{tmp.memberInfo._id}}</td>
                    <td>{{tmp.memberInfo.name}}</td>
                    <td>{{tmp.memberInfo.email}}</td>
                    <td>{{tmp.memberInfo.phone}}</td>

                </tr>
            </table>

            <div style="width:600px; border: 1px solid #cccccc; padding:30px">
                <vue3-chart-js v-bind="chartData" ref="chartRef"/>
            </div>
        </div>

        <div v-show="state.menu===2">
            <h4>회원별 주문내역</h4>
            <table border="1">
                <tr>
                    <th>구매자아이디</th>
                    <th>구매자이름</th>
                    <th>구매자 이메일</th>
                    <th>구매자 번호</th>
                    <th>주문개수</th>
                    <th>주문수량합계</th>
                    <th>주문수량평균</th>
                    <th>최대주문수량</th>
                </tr>
                <tr v-for="tmp of state.rows2" :key="tmp">
                    <td>{{tmp.memberInfo._id}}</td>
                    <td>{{tmp.memberInfo.name}}</td>
                    <td>{{tmp.memberInfo.email}}</td>
                    <td>{{tmp.memberInfo.phone}}</td>
                    <td>{{tmp.orderInfo.count}}</td>
                    <td>{{tmp.orderInfo.total}}</td>
                    <td>{{tmp.orderInfo.avg}}</td>
                    <td>{{tmp.orderInfo.max}}</td>

                </tr>
            </table>

            <div style="width:600px; border: 1px solid #cccccc; padding:30px">
                <vue3-chart-js v-bind="chartData2" ref="chartRef2"/>
            </div>
        </div>

    </div>
</template>

<script>
import { reactive, ref } from '@vue/reactivity'
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';

import Vue3ChartJs from '@j-t-mcc/vue3-chartjs'
import { useRouter } from 'vue-router';
export default {
    components:{
        Vue3ChartJs
    },

    setup () {

        const router = useRouter();

        // 차트에서 사용
        const chartRef = ref(0);
        const chartData = reactive({
            type : "bar", // 차트 종류
            options : {
                plugins:{
                    legend :{
                        position : 'right'
                    }
                }
            },
            data : {
                labels : [ 'html', 'css', 'js', 'vue3'],
                datasets : [
                    {
                        label:'주문개수',
                        backgroundColor : ['#1abc9c', '#1abc9c', '#1abc9c', '#1abc9c'],
                        data :[10,50,40,20]
                    },
                    {
                        label:'주문수량합계',
                        backgroundColor : ['#123456', '#123456', '#123456', '#123456'],
                        data :[10,50,40,20]
                    },
                    {
                        label:'주문수량평균',
                        backgroundColor : ['#c2312c', '#c2312c', '#c2312c', '#c2312c'],
                        data :[10,50,40,20]
                    }
                ]
            }
        });
        // 차트에서 사용
        const chartRef2 = ref(1);
        const chartData2 = reactive({
            type : "bar", // 차트 종류
            options : {
                plugins:{
                    legend :{
                        position : 'right'
                    }
                }
            },
            data : {
                labels : [ 'html', 'css', 'js', 'vue3'],
                datasets : [
                    {
                        label:'주문개수',
                        backgroundColor : ['#1abc9c', '#1abc9c', '#1abc9c', '#1abc9c'],
                        data :[10,50,40,20]
                    },
                    {
                        label:'주문수량합계',
                        backgroundColor : ['#123456', '#123456', '#123456', '#123456'],
                        data :[10,50,40,20]
                    },
                    {
                        label:'주문수량평균',
                        backgroundColor : ['#c2312c', '#c2312c', '#c2312c', '#c2312c'],
                        data :[10,50,40,20]
                    },
                    {
                        label:'최대주문수량',
                        backgroundColor : ['#22352c', '#22352c', '#22352c', '#22352c'],
                        data :[10,50,40,20]
                    },
                ]
            }
        });
        
        
        //주문목록에서 사용
        // 주문목록에서 사용
        const state = reactive({
            rows    : [],
            rows2   : [],
            menu    : 1,
            token   : sessionStorage.getItem("TOKEN")
        });

        onMounted(()=> {
            handleData();
            handleData2();
        });

        const handleData = async() => {
            const url = `/order/groupitem.json`;
            const headers = {
                "Content-Type":"application/json",
                "token" : state.token
            };
            const { data } = await axios.get(url, {headers});
            console.log(data);
            if(data.status === 200){
                state.rows = data.result;

                // tmp =>     [{_id:8},{_id:9},{_id:10}]
                // 변경모양 => [ 8, 9, 10]
                let arr = [];
                for(let tmp of data.result3){
                    arr.push( `물품번호 : ${tmp._id}` );
                }
                chartData.data.labels = arr;

                // tmp =>     [{count:8},{count:9},{count:10}]
                // 변경모양 => [ 8, 9, 10]
                let arr1 = [];
                let arr2 = [];
                let arr3 = [];
                for(let tmp of data.result3){
                    arr1.push( tmp.count );
                    arr2.push( tmp.total );
                    arr3.push( tmp.avg );
                }
                chartData.data.datasets[0].data = arr1;
                chartData.data.datasets[1].data = arr2;
                chartData.data.datasets[2].data = arr3;

                // ref를 이용한 차트 갱신하기
                chartRef.value.update(200);
            }
        };


        const handleData2 = async() =>{
            const url = `/order/groupmember.json`;
            const headers = {
                "Content-Type":"application/json",
                "token" : state.token
            };
            const { data } = await axios.get(url, {headers});
            console.log(data);
            if(data.status === 200){
                state.rows2 = data.result

                let arr4 = [];
                for(let tmp of data.result){
                    arr4.push( `구매자이름 : ${tmp.memberInfo.name}` );
                }
                console.log(arr4);
                chartData2.data.labels = arr4;

                let arr5 = [];
                let arr6 = [];
                let arr7 = [];
                let arr8 = [];
                for(let tmp of data.result){
                    arr5.push( tmp.orderInfo.count );
                    arr6.push( tmp.orderInfo.total );
                    arr7.push( tmp.orderInfo.avg );
                    arr8.push( tmp.orderInfo.max );
                }
                chartData2.data.datasets[0].data = arr5;
                chartData2.data.datasets[1].data = arr6;
                chartData2.data.datasets[2].data = arr7;
                chartData2.data.datasets[3].data = arr8;

                // ref를 이용한 차트 갱신하기
                chartRef2.value.update(200);
            }
        };

        const handleContent = (tmp) =>{
            router.push({path:'/itemcontent', query:{code:tmp}})
        }

        return {state, chartRef, chartData, chartRef2, chartData2, handleContent}
    }
}
</script>

<style lang="scss" scoped>

</style>

차트1까지는 선생님과 같이 만듬

실습 위주로 수업

차트2 +

아이템 코드(물품 번호) 클릭시 상세 물품페이지로 이동하는 것

직접 만들어봤음.