QuasarFramework(Vue.js)で、Firestoreを使ってみる。

Realtime Databaseの進化版という噂のFirestoreをVue.jsのプロジェクトで使ってみました。

# 参考
https://firebase.google.com/docs/firestore/quickstart?hl=ja
https://qiita.com/1amageek/items/8179aebe871beb230194

# 前提・環境
Vue.js, QuasarFrameworkなどで、Firebaseに作成しているアプリなどがある。
まだの方は、以下の記事など参照にしていただけますと幸いです。
https://qiita.com/yassyskywalker/items/d74ea3b0834145df5473

# Realtime Databaseと違うところ
こちらの記事がものすごくわかりやすかったです！
https://qiita.com/1amageek/items/8179aebe871beb230194

要は、Realtime Databaseの進化した形がFirestoreのようです！
これは使うっきゃねー！という感じです！

# Vue.jsプロジェクトに、Firestoreを導入する
Firestoreに関しては、ベータ版のため、手動でimportする必要があるようです。
firebaseをnpm installして、main.jsに記入します。

```shell
npm install firebase --save
```

```JavaScript:main.js
import Vue from 'vue'
import firebase from 'firebase'
// Firestoreのimport
require('firebase/firestore')

// Firestoreの初期化
firebase.initializeApp({
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
  projectId: '### CLOUD FIRESTORE PROJECT ID ###'
})

var db = firebase.firestore()
```

# Firestoreをつかってみる。
Realtime Databaseと少し違います。よりSQLに近くなったな〜とぼんやり思っています。

## コレクション・ドキュメントの追加
usersコレクションを、authuserのUIDを利用して、作成してみます。

参考:
https://firebase.google.com/docs/firestore/query-data/get-data?hl=ja

* collectionにデータを追加するときは、addメソッドを使います。

```javascript
const db = firebase.firestore()
db.collection("users").add({
    first: "Ada",
    last: "Lovelace",
    born: 1815
})
```

* ドキュメントID を指定する場合は、docで参照して、setメソッドでデータを追加します。

```JavaScript
methods: {
  const user = firebase.auth().currentUser
  const uid = user.uid
  const db = firebase.firestore()
  db.collection('users').doc(uid).set(this.newUser)
}
```

シンプルでわかりやすそうですね!

## コレクション・ドキュメントのデータの取得

```html
<script>
methods: {
  const user = firebase.auth().currentUser
  const uid = user.uid
  const db = firebase.firestore()
  // collection内のすべてのデータを取得する
  db.collection('users').get().then((querySnapshot) => {
    querySnapshot.forEach((doc) => {
        console.log(`${doc.id} => ${doc.data()}`)
    })
  })
  // ドキュメントを指定してデータを取得する
  db.collection('users').doc(uid).get().then((doc) => {
    if (doc.exists) {
      console.log(doc.data())
    }
    else {
      console.log('documentがありません。')
    }
  })
  .catch((err) => {
    console.log(err)
  })
  // whereでドキュメントのフィールドに合致するドキュメントを検索できる
  db.collection('users').where('username', '==', 'yassy')
    .get()
    .then((querySnapshot) => {
      querySnapshot.forEach((doc) => {
        console.log(doc.id, ' => ', doc.data())
      })
    })
    .catch((err) => {
      console.log(err)
    })
}
</script>
```

whereはかなり便利そう！ますますSQLライクになってる気がします。

# QuasarFramework(Vue.js) + Firestoreで、ユーザー情報を作成する

```html:Singup.vue
<template lang="html">
  <div>
    <div class="layout-padding row justify-center background-whitesmoke items-center">
      <div class="col-xs-12 col-sm-7 col-lg-5">
        <q-card class="q-card-background-white">
          <q-card-main>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-center">
                <img src="~assets/quasar-logo-full.svg" class="logo-sized">
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-left">
                <h5>新規登録</h5>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1 text-left">
                <p style="font-size: 12px;">新規アカウントの登録をお願いします。</p>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1">
                <q-field>
                  <q-input
                    v-model="username"
                    float-label="ユーザー名"
                    color="primary"
                    type="text"
                    pattern="^[0-9A-Za-z]+$"/>
                </q-field>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1">
                <q-field>
                  <q-input v-model="email" float-label="メールアドレス" color="primary" type="email"/>
                </q-field>
              </div>
            </div>
            <div class="row">
              <div class="col-sm-10 offset-sm-1">
                <q-field>
                  <q-input v-model="password" float-label="パスワード" color="primary" type="password"/>
                </q-field>
              </div>
            </div>
            <div class="row" style="padding-top: 20px;">
              <div class="col-sm-10 offset-sm-1 text-right">
                <q-btn color="primary" style="font-weight: bold;" @click="signUp">新規登録</q-btn>
              </div>
            </div>
            <br>
            <div class="row">
              <p style="color:#027be3;font-size:12px;"><router-link :to="{ name: 'Login' }">すでに登録済みの方はサインインしてください</router-link></p>
            </div>
          </q-card-main>
        </q-card>
      </div>
    </div>
  </div>
</template>

<script>
import {
  QBtn,
  QCard,
  QCardMain,
  QField,
  QInput
} from 'quasar'
import firebase from 'firebase'

export default {
  name: 'signUpFirestore',
  components: {
    QBtn,
    QCard,
    QCardMain,
    QField,
    QInput
  },
  data () {
    return {
      username: '',
      password: '',
      email: '',
      user_uid: '',
      newUser: {
        name: '',
        username: '',
        homepage: '',
        comment: '',
        tel: '',
        sex: '',
        public: true
      }
    }
  },
  methods: {
    signUp () {
      firebase.auth().createUserWithEmailAndPassword(this.email, this.password).then(
        (user) => {
          console.log('新規auth userの登録成功!')
          this.createNewUser(user)
          // Emailの確認もつけておく
          user.sendEmailVerification().then(
            () => {
              alert('認証')
            },
            (err) => {
              alert('EmailVerificationでerrが発生しました。', err)
            }
          )
          this.$router.replace('/')
        },
        (err) => {
          let errorCode = err.code
          let errorMessage = err.message
          alert(errorCode, errorMessage)
        }
      )
    },
    createNewUser (user) {
      // UserのUIDをPKにして、users テーブルを作成する
      const uid = user.uid
      const username = this.username
      const db = firebase.firestore()
      this.newUser.username = username
      db.collection('users').doc(uid).set(this.newUser)
        .then(() => {
          console.log('userコレクションの作成成功!')
        })
        .catch((err) => {
          console.log(err)
        })
    }
  }
}
</script>
<style lang="stylus">
.q-card-background-white
  background white
.background-whitesmoke
  background whitesmoke
  height 100vh
.logo-sized
  width 150px
  margin 20px
</style>
```

Firebaseのコンソールで確認して、コレクションにデータが表示されていれば成功です！

# usernameの重複をチェックする
firestoreのusersコレクションをチェックして、usernameの重複がないかを確認してから登録します。

```javascript
methods: {  
  validateUsername () {
    const username = this.username
    if (username !== '') {
      const db = firebase.firestore()
      db.collection('users').where('username', '==', username).get()
        .then((querySnapshot) => {
          if (querySnapshot.empty) {
            console.log('重複するusername無し:', querySnapshot)
            this.validation.username = true
          }
          else {
            console.log('重複するusername有り', querySnapshot)
            this.validation.username = false
          }
        })
        .catch((err) => {
          console.log(err)
        })
    }
  },
}
```

恐らくもっといい方法がありそうな気がするので、もし何かありましたら、ご教示いただけますと幸いです。

# まとめ
個人的に、firestoreは、SQLぽい感覚で指示ができるので、かなり使いやすそうだなと感じました。あとクエリが強力そうなのも嬉しいですね。
今後は、firestore積極的に活用していきたいです！