Vue로 PWA 개발 - 그랜파 개발자
‘내로그’ 메뉴를 눌러 나의 마이로그 목록을 볼 때 기본은 작성일 역순으로 보입니다. 그런데 마이로그 중 조회순으로 보고 싶을 때가 있습니다. 그래서 ‘내로그’ 페이지에 정렬 방법에 대한 ‘최신순’, ‘조회순’ 두 개의 버튼을 추가합니다. ‘최신순’은 작성일 역순으로 정렬을 하고, ‘조회순’은 조회수가 많은 순서로 정렬하여 보여줍니다.
1. 쿼리
마이로그 보기 정렬을 위한 쿼리입니다.
- 최신순 쿼리입니다.
query(collection(db, "mylogs"), where("userId", "==", userId), orderBy("createdAt", "desc")); - 조회순 쿼리입니다.
query(collection(db, "mylogs"), where("userId", "==", userId), orderBy("views", "desc"));
위의 쿼리를 보면 where와 orderBy를 사용합니다. 이로 인해 복합 색인이 필요합니다.
firestore는 단일 필드 색인, 복합 색인이 있습니다.
- 단일 필드 색인(single field index) - 필드 하나로 구성된 색인
- 복합 색인(composite index) - 필드 여러개로 구성된 색인
Firestore에서는 자동으로 생성되는 단일 필드 색인과는 달리 복합 색인을 자동으로 만들지 않습니다. 가능한 필드 조합 수가 많기 때문입니다. 대신 Firestore를 통해 앱을 빌드할 때 필요한 복합 색인을 식별하고 만들 수 있습니다.
필수 색인부터 만들지 않고 위의 쿼리를 시도하면 Firestore에서 링크가 포함된 오류 메시지를 반환합니다. 이 링크로 이동하면 누락된 색인을 만들 수 있습니다. 색인에서 지원하지 않는 쿼리를 시도할 때마다 이러한 오류가 발생합니다. 또한 Console이나 Firebase CLI를 사용하여 직접 복합 색인을 정의하고 관리할 수 있습니다.
Firebase Console에서 수동으로 새 색인을 만들려면 다음과 같이 합니다.
- Firebase Console의 Cloud Firestore 섹션으로 이동합니다.
- 색인 탭으로 이동하고 색인 추가를 클릭합니다.
- 컬렉션 이름을 입력하고 색인의 정렬 기준으로 사용할 필드를 설정합니다.
- 만들기를 클릭합니다.
https://cloud.google.com/firestore/docs/concepts/index-overview?hl=ko 참조했습니다.
2. 마이로그 정렬
3. src/views/MyMyLogsView.vue
<!-- src/views/MyMyLogsView.vue -->
<template>
<v-container>
<v-card>
<v-card-title>{{ getMylogName }}</v-card-title>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn @click="viewByDate"> 최신순 </v-btn>
<v-btn @click="viewByViews"> 조회순 </v-btn>
</v-card-actions>
<v-list v-if="userMylogs.length > 0">
<v-list-item v-for="mylog in userMylogs" :key="mylog.id" @click="goToMylogDetail(mylog.id)">
<v-list-item-content>
<v-list-item-title>{{ mylog.title }}</v-list-item-title>
<v-list-item-subtitle>{{ mylog.createdAt.toDate().toLocaleDateString() }} ({{ mylog.views }})</v-list-item-subtitle>
<v-list-item-subtitle>{{ mylog.content }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</v-list>
<p v-else>You haven't written any posts yet.</p>
</v-card>
</v-container>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
export default {
data() {
return {
};
},
computed: {
...mapGetters('mylogs',['userMylogs']),
getMylogName() {
return this.$store.state.auth.user.mylogname;
}
},
methods: {
...mapActions('mylogs', ['fetchUserMylogs', 'fetchUserMylogsOrderByViews']),
goToMylogDetail(mylogId) {
this.$router.push({ name: 'MyLogView', params: { id: mylogId } });
},
viewByDate() {
const userId = this.$store.state.auth.user.id;
this.fetchUserMylogs(userId); // 본인 작성 글 가져오기
},
viewByViews() {
const userId = this.$store.state.auth.user.id;
this.fetchUserMylogsOrderByViews(userId); // 본인 작성 글 가져오기
}
},
mounted() {
const userId = this.$store.state.auth.user.id;
this.fetchUserMylogs(userId); // 본인 작성 글 가져오기
}
};
</script>
4. src/store/modules/mylogs.js
// src/store/modules/mylogs.js
import router from '@/router'; // Vue Router import
import { v4 as uuidv4 } from 'uuid';
import { db, doc, collection, getDoc, getDocs, addDoc, setDoc, updateDoc } from "@/firebase";
import { deleteDoc, query, orderBy, arrayUnion, increment, where } from "@/firebase";
const state = {
. . .
userMylogs: [], // 본인이 작성한 글 저장
. . .
};
const mutations = {
. . .
setUserMylogs(state, mylogs) {
state.userMylogs = mylogs;
},
. . .
};
const actions = {
. . .
// 현재 사용자가 작성한 게시물 불러오기 - 조회수 역순 정렬
async fetchUserMylogsOrderByViews({ commit }, userId) {
if (userId) {
try {
const q = query(collection(db, "mylogs"), where("userId", "==", userId), orderBy("views", "desc"));
const querySnapshot = await getDocs(q);
const mylogs = [];
querySnapshot.forEach((doc) => {
mylogs.push({ id: doc.id, ...doc.data() });
});
commit('setUserMylogs', mylogs); // 상태에 저장
} catch (error) {
console.error("본인 글 가져오기 실패:", error);
commit('setError', error);
}
}
},
// 현재 사용자가 작성한 게시물 불러오기 - 작성일 역순 정렬
async fetchUserMylogs({ commit }, userId) {
if (userId) {
try {
const q = query(collection(db, "mylogs"), where("userId", "==", userId), orderBy("createdAt", "desc"));
const querySnapshot = await getDocs(q);
const mylogs = [];
querySnapshot.forEach((doc) => {
mylogs.push({ id: doc.id, ...doc.data() });
});
commit('setUserMylogs', mylogs); // 상태에 저장
} catch (error) {
console.error("본인 글 가져오기 실패:", error);
commit('setError', error);
}
}
},
. . .
};
const getters = {
. . .
userMylogs: state => state.userMylogs,
. . .
};
export default {
namespaced: true,
state,
mutations,
actions,
getters
};
'Vue로 PWA 개발' 카테고리의 다른 글
62. mylog 끝 (0) | 2024.11.03 |
---|---|
60. myLog 날짜별 조회수 구현 (0) | 2024.11.03 |
59. myLog 날짜별 조회수 (1) | 2024.11.03 |
58. mylog 통계 (0) | 2024.11.03 |
57. mylog 구독자 알림 전송 (0) | 2024.11.02 |