将具有列表属性的自定义模型作为具有子集合的文档进行管理

Managing custom models with list attributes as documents with subcollections

我有一个 Contact 模型,它包含不同的属性和属性列表。现在我想将这些存储在 Firestore 中,但将列表作为相应文档的子集合。

Contact 模型的最小示例如下所示(请注意,该列表已从地图中排除):

class Contact(private val map: MutableMap<String, Any?>){
    var nameDisplay:String? by map
    var nickname:String? by map
    var organisation:String? by map
    val phones:ArrayList<Phone> = ArrayList()
}

在 Firestore 中使用此表示:

contacts:
    contact1
        nameDisplay = "Test"
        nickname = "Test"
        organisation = "some corp"
        phones:
            phone1
                number = 8243525
                label = "this guy"
            phone2
                number = 8243525433
                label = "this guy"
    contact2
        ....

我正在寻找一种最佳实现此行为的方法。

我找到的一个可行的解决方案是使用辅助构造函数,我可以在其中单独传递集合。

期望的实现是自定义对象的默认实现,但具有上述行为:

var contact: Contact = documentSnapshot.toObject(Contact::class.java);

我认为你过度设计了。 Kotlin 让这些属性通过参数从构造函数初始化比你正在做的疯狂委托要好得多。 (尽管我必须为您将语言推向极限而鼓掌!)碰巧的是,toObject 方法与这些最佳实践配合得非常好。所以你的 Contact class 应该看起来像这样:

data class Contact(
        @Exclude
        @get:Keep
        @set:Keep
        var nameDisplay: String? = null,

        @Exclude
        @get:Keep
        @set:Keep
        var nickname: String? = null,

        @Exclude
        @get:Keep
        @set:Keep
        var organisation: String? = null,

        @Exclude
        @get:Keep
        @set:Keep
        @set:RestrictTo(RestrictTo.Scope.TESTS) // Hack b/c Firebase needs a setter but we don't
        var phones: Map<String, Any?> = mapOf()
) {
    val phoneObjects: MutableList<User> by lazy {
        phones.parse() // Map them to your phone objects
    }
}

这有点难看,但可以让您使用 toObject 方法。代码更多但数据更漂亮的版本 class 将使用 snapshot.getString(...) 手动传递参数。但是,如果你真的想走委托路线,我很确定你也可以将手机 属性 委托给地图,然后只传递快照数据:Contact(snapshot.data).