You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将含列表属性的自定义模型以文档+子集合形式存储于Firestore

Hey there! Let's walk through how to store your Contact model in Firestore, with the phones list saved as a subcollection under the contact document. Here's a step-by-step breakdown with code examples:

Step 1: Basic Setup & Saving the Core Contact Data

First, get your Firestore instance and prepare to save the main contact properties (from the map in your Contact class) as a document in a contacts collection.

import com.google.firebase.firestore.FirebaseFirestore
import android.util.Log

// Initialize Firestore instance
val db = FirebaseFirestore.getInstance()

fun saveContact(contact: Contact) {
    // Generate a unique document ID for the contact (or use a custom ID if you have one)
    val contactDocRef = db.collection("contacts").document()
    
    // Save the contact's core properties (from the map) to the document
    contactDocRef.set(contact.map)
        .addOnSuccessListener {
            Log.d("Firestore", "Contact document saved successfully")
            // Once the main document is saved, handle the phones subcollection
            savePhonesSubcollection(contactDocRef, contact.phones)
        }
        .addOnFailureListener { e ->
            Log.e("Firestore", "Failed to save contact document", e)
        }
}
Step 2: Saving the Phones as a Subcollection

Next, we'll take the phones ArrayList and store each Phone as a document in a phones subcollection under the contact's document. Using a batch write ensures atomicity (all phones save successfully, or none do).

First, make sure your Phone class can convert its properties to a Map (Firestore requires this for storage):

class Phone(
    val number: String,
    val type: String // e.g., "mobile", "home", "work"
) {
    // Convert Phone object to a Firestore-compatible Map
    fun toMap(): Map<String, Any> {
        return mapOf(
            "number" to number,
            "type" to type
        )
    }
}

Then, implement the subcollection save function:

private fun savePhonesSubcollection(contactDocRef: DocumentReference, phones: ArrayList<Phone>) {
    val phonesCollection = contactDocRef.collection("phones")
    val batch = db.batch()

    // Add each phone to the batch write
    phones.forEach { phone ->
        val phoneDocRef = phonesCollection.document() // Generate unique ID for each phone
        batch.set(phoneDocRef, phone.toMap())
    }

    // Commit the batch
    batch.commit()
        .addOnSuccessListener {
            Log.d("Firestore", "Phones subcollection saved successfully")
        }
        .addOnFailureListener { e ->
            Log.e("Firestore", "Failed to save phones subcollection", e)
        }
}
Step 3: Loading the Contact with Its Phones

When you need to retrieve a contact later, you'll first fetch the main document, then fetch its phones subcollection:

fun loadContact(contactId: String, onComplete: (Contact?, List<Phone>?) -> Unit) {
    val contactDocRef = db.collection("contacts").document(contactId)

    // Fetch the main contact document
    contactDocRef.get()
        .addOnSuccessListener { contactDoc ->
            if (contactDoc.exists()) {
                val contact = Contact(contactDoc.data as MutableMap<String, Any?>)
                
                // Fetch the phones subcollection
                contactDocRef.collection("phones").get()
                    .addOnSuccessListener { phonesSnapshot ->
                        val phones = phonesSnapshot.documents.mapNotNull { phoneDoc ->
                            Phone(
                                phoneDoc.getString("number") ?: "",
                                phoneDoc.getString("type") ?: ""
                            )
                        }
                        contact.phones.addAll(phones)
                        onComplete(contact, phones)
                    }
                    .addOnFailureListener { e ->
                        Log.e("Firestore", "Failed to load phones", e)
                        onComplete(contact, null)
                    }
            } else {
                onComplete(null, null)
            }
        }
        .addOnFailureListener { e ->
            Log.e("Firestore", "Failed to load contact", e)
            onComplete(null, null)
        }
}
Key Notes
  • Why a subcollection? Storing phones as a subcollection avoids hitting Firestore's 1MB document size limit (critical if contacts can have many phone numbers). It also makes querying individual phone entries easier later.
  • Document IDs: We're using auto-generated IDs for both contacts and phones, but you can use custom IDs (like a unique contactId or phoneId from your model) if you need direct access to specific documents.
  • Atomicity: Using batch writes for phones ensures that if one phone fails to save, none are saved—this keeps your data consistent.

内容的提问来源于stack exchange,提问作者Niels

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:22:45