LoginSignup
9
3

More than 3 years have passed since last update.

[Android] Firebase Cloud Firestore を使ってデータを追加・削除・取得する

Last updated at Posted at 2020-04-11

はじめに

Firebase の Cloud Firestore を使ったことがありませんでした。今更な感じですがどんなものか知るために Cloud Firestore を使ってデータの追加・削除・取得をやってみたいと思います。

-------------------------------------------------------------------------------------------
◆ Cloud Firestore とは? ◆
-------------------------------------------------------------------------------------------
Firebase の Cloud Firestore は クラウドホスト型の NoSQLデータベース です。
Cloud Firestore は iOS アプリや Android アプリおよびWebアプリから SDK を介して直接アクセスできます。
-------------------------------------------------------------------------------------------

Firebase のプロジェクトを作成する

Firebase ではプロジェクトを作成し、そのプロジェクトで設定を行うことで Cloud Firestore を利用できるようにします。 なのでまずは次の手順で Firebase のプロジェクトを作成していきます。

  1. [Firebase] にログインし、「プロジェクト」の作成を選択する。 (FirebaseはGoogleのアカウントでログインできます。)
  2. 「プロジェクト名」に任意の名称を入力して、「続行」を選択する。
  3. 「Googleアナリティクス」を有効・無効どちらか選択し、「続行」を選択する
  4. 「Googleアナリティクスアカウント」を選択し、「続行」を選択する (特に何もなければ、Default Account for Firebase でよいはず)
  5. Firebase のコンソールに移動し、作成した Firebase プロジェクトを選択する。

Android プロジェクトを作成する

Android プロジェクトを作成して、Cloud Firestore を利用できるようにします。
まずば Firebase プロジェクト上で次の操作でセットアップを行います。

  1. Firebase のコンソールで Firebase プロジェクトを選択する。
  2. アプリを追加 を選択し、プラットフォーム で Android を選択する。
  3. Androidパッケージ名の入力が求められるので、Android プロジェクトのパッケージ名を入力し、次へを選択する。
  4. 設定ファイルのダウンロードで、google-service.json をダウンロードする。
  5. Firebase SDK の追加アプリを実行してインストールを確認は後で確認するので、次へを選択する。

そして Android Studio 上で Android プロジェクトのセットアップを行います。

  1. [Android Studio]Android プロジェクトを作成する。
  2. [Andriod Studio]app に google-service.json をコピーする
  3. [Android Studio]build.gradle で必要なライブラリを加える
buildscript {
    ext.kotlin_version = '1.3.71'
    repositories {
        google() // 追加する
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:4.3.3' // 追加する
    }
}

allprojects {
    repositories {
        google() // 追加する
        jcenter()

    }
}
apply plugin: 'com.google.gms.google-services'

dependencies {
       
    def firebase_analytics_version = "17.3.0"
    implementation "com.google.firebase:firebase-analytics:${firebase_analytics_version}"

    def firebase_fire_store_version = "21.4.2"
    implementation "com.google.firebase:firebase-firestore:${firebase_fire_store_version}"
       
}

これで Android アプリ から Cloud Firestore にアクセスできるようになります。

Cloud Firestore で Task を追加・削除・取得する

Cloud Firestore は NoSQLデータベースで、ドキュメントデータベースのデータモデルに従ってデータを管理します。データモデルとしてコレクション・ドキュメント・データとありこれを組み合わせてデータを管理します。

データ
コレクション 複数のドキュメントを格納し、
データの編集やクエリなどを実行するためのデータモデル
ドキュメント データを格納するデータモデル
データ 単純な文字列から数値などを格納するデータモデル
(サポートしているデータ・タイプ)

Image from Gyazo

今回は次の Task クラスを定義し、次のデータモデル構成で Task オブジェクトを管理してみたいと思います。

data class Task(val id: String, val time: Long, val name: String) {
    companion object {
        fun create(name: String): Task = Task(UUID.randomUUID().toString(), Date().time, name)
    }
}

Image from Gyazo

データベースを取得する

Cloud Firestore でデータベースを制御するには FirebaseFireStore オブジェクトを利用します。次のコードで FirebaseFireStore オブジェクトを取得します。

private val database : FirebaseFirestore get() = FirebaseFirestore.getInstance()

ドキュメントを追加し、Taskデータを保存する

どのコレクションのドキュメントを追加するか決めます。FirebaseFirestore.collection(name: String) に名前を入力しコレクションを取得します。コレクションを取得したらCollection.document(name:String)に任意の名前を入力しドキュメントを作成します。名前を指定しない Collection.document() でも作成でき、これだとドキュメントの名称は自動で生成されます。

ドキュメントができたらデータを追加するだけですが、データは Map<String, *> である必要があります。今回は Task.toMap を用意しました、これで Map<String, *> に変換して Document.set してやれば Task オブジェクトを保存できます。

suspend fun add(task: Task): Boolean {
    try {
        val collection = database.collection("CollectionName")
        val document = collection.document(task.id)
        val data = task.toHashMap()
        document.set(data).await()
        return true
    } catch (e: Exception) {
        return false
    }
}

fun Task.toMap(): Map<String, *> {
    return hashMapOf(
        "id" to this.id,
        "time" to this.time,
        "name" to this.name
    )
}

ドキュメントを削除し、Taskデータを削除する

どのコレクションのドキュメントを削除するか決めます。FirebaseFirestore.collection(name: String) に名前を入力しコレクションを取得します。コレクションを取得したらCollection.document(name:String)で削除するドキュメントを取得します。あとはdocument.delete()を実行するとドキュメントが削除され、そこに格納されていた Task データも削除されます。

suspend fun delete(task: Task): Boolean {
    try {
        val collection = database.collection("CollectionName")
        val document = collection.document(task.id)
        document.delete().await()
        return true
    } catch (e: Exception) {
        return false
    }
}

ドキュメントを検索し、 ある Task データを取得する

どのコレクションのドキュメントを検索するか決めます。FirebaseFirestore.collection(name: String) に名前を入力しコレクションを取得します。コレクションにはlimitorderByなどのクエリが用意されており、取得するドキュメントを指定できるようになっています。今回はlimitを使ってある上限数を以内のドキュメントを取得するようにします。

ドキュメントからデータを取得するだけですが、データは Map<String, *> であるので、Taskに変換する必要があります。今回は Map<String, *>.toTask を用意して、これで取得したドキュメントのデータを Task に変換してやれば Task オブジェクトの取得ができます。

suspend fun fetchTask(limit: Long): List<Task> {
    try {
        val collection = database.collection("CollectionName")
        val documents = collection.limit(limit).get().documents
        return documents.map { it.data }.mapNotNull { it?.toTask() }
    } catch (e: Exception) {
        return listOf()
    }
}
fun Map<String, Any>.toTask(): Task {
    val id = this["id"] as String
    val time = this["time"] as Long
    val name = this["name"] as String
    return Task(id, time, name)
}

実際に動かしてみる

これでドキュメントの追加・削除・取得ができるようになりました。
これらの処理を TaskRepository にまとめると次のような感じになります。

class TaskRepository {
    private val database : FirebaseFirestore get() = FirebaseFirestore.getInstance()

    suspend fun add(task: Task): Boolean {
        try {
            val collection = database.collection(COLLECTION_PATH)
            val document = collection.document(task.id)
            val data = task.toHashMap()
            document.set(data).await()
            return true
        } catch (e: Exception) {
            return false
        }
    }

   suspend fun delete(task: Task): Boolean {
        try {
            val collection = database.collection(COLLECTION_PATH)
            val document = collection.document(task.id)
            document.delete().await()
            return true
        } catch (e: Exception) {
            return false
        }
    }

    suspend fun fetchTask(limit: Long): List<Task> {
        try {
            val collection = database.collection("CollectionName")
            val documents = collection.limit(limit).get().documents
            return documents.map { it.data }.mapNotNull { it?.toTask() }
        } catch (e: Exception) {
            return listOf()
        }
    }

    companion object {
        private const val COLLECTION_PATH = "tasks"
    }
}

次のようにTaskRepositoryを使って取得・追加・削除の処理を記述してみましょうか。

class MainActivity : AppCompatActivity() {
    private val repository: TaskRepository = TaskRepository()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        lifecycleScope.launch {
            // ①現在のタスク一覧を取得する
            println("①現在のタスク一覧を取得する ▶ " + repository.fetchTask(100))

            // ②新しいタスクを追加する
            val newTask = Task.create("New Task")
            repository.add(newTask)
            println("①新しいタスクを追加する ▶ " + repository.fetchTask(100))

            // ③新しく追加したタスクを削除する
            repository.delete(newTask)
            println("③新しく追加したタスクを削除する ▶ " + repository.fetchTask(100))
        }
    }
}

実行結果は次のようになりました、取得・追加・削除がうまく動作していますね。

①現在のタスク一覧を取得する ▶ []
②新しいタスクを追加する ▶ [Task(id=8895dfb2-4aa0-4da0-bf3e-72da7a192fb8, time=1586591310782, name=New Task)]
③新しく追加したタスクを削除する ▶ []

おわりに

Firebase Cloud Firestore のチュートリアルではさらっとドキュメントデータベースであることが書かれていますが、ドキュメントデータベースであることがわからないとどれだけ API の仕様を眺めて Cloud Firestore を理解できないですね。NoSQLやドキュメントデータベースのコンセプトがわかると一気に理解できるようになりました。まだデータ構造など何が最適化わからないですが、非常に強力な開発環境だと思うので少しずづ使えるようになっていきたいですね。

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3