无法从Firestore获取Timestamp文档字段

时间:2018-05-14 15:04:36

标签: android firebase google-cloud-firestore

从Firestore获取数据时,我无法获取时间戳字段。

My Room文档的结构如下:

enter image description here

我正在从Firestore那里得到房间,如下所示。

助手类:

    fun getRooms(userId: String): Task<QuerySnapshot> {
        return FirebaseFirestore.getInstance()
                .collection(KEY_USERS).document(userId)
                .collection(KEY_ROOMS).get()
    }

Interactor class:

private fun getRooms(): Task<List<Room>> {
    val source = TaskCompletionSource<List<Room>>()
    val listener = OnCompleteListener<QuerySnapshot> {
        if (it.isSuccessful) {
            val roomSnapshots = it.result
            if (!roomSnapshots.isEmpty) {
                val rooms = ArrayList<Room>()
                for (roomSnapshot in roomSnapshots) {
                    rooms.add(Room(roomSnapshot))
                }
                source.setResult(rooms)
            }
        } else {
            source.setException(it.exception!!)
        }
    }
    FirebaseFireStoreHelper.getRooms(mUserId).addOnCompleteListener(listener)
    return source.task
}

我的Room模特课:

class Room(document: DocumentSnapshot) {

    companion object {
        private const val KEY_DATE_CREATED = "dateCreated"
        private const val KEY_TITLE = "title"
    }

    private lateinit var mId: String
    private lateinit var mDateCreated: Date
    private lateinit var mTitle: String

    init {
        if (document.exists()) {
            mId = document.id
            mDateCreated = document.getDate(KEY_DATE_CREATED)!!
            mTitle = document.getString(KEY_TITLE)!!
        }
    }

    fun getId(): String = mId

    fun getDateCreated(): Date? = mDateCreated

    fun getTitle(): String = mTitle

}

问题是document.getDate(KEY_DATE_CREATED)始终返回null。我尝试使用get(KEY_DATE_CREATED)getString(KEY_DATE_CREATED)来查看我是否可以获得任何价值,但无济于事。

经过几次尝试后,我测试了整个对象的打印情况,并且能够得到这个:

DocumentSnapshot{
    key=users/kCKkmgLmLGfvbPFK09qyZ5uoyw32/rooms/R35Bj56rda7pkkYWH1MQ,
    metadata=SnapshotMetadata{
        hasPendingWrites=false,
        isFromCache=false
    },
    doc=Document{
        key=users/kCKkmgLmLGfvbPFK09qyZ5uoyw32/rooms/R35Bj56rda7pkkYWH1MQ,
        data=zza{
            (title=>Sample Room)
        };,
    version=SnapshotVersion(seconds=1523285961, nanos=350799000),
    hasLocalMutations=false
    }
}

显然,首先没有检索dateCreated字段,这解释了空值。从我的代码中,我相信我正在正确处理解析。令人困惑的是,我还有一个Message对象,其中包含dateCreated时间戳字段,我能够正确地获取它。

P.S。:示例代码在Kotlin中,我可以发布Java代码版本,如果它可以帮助使事情更清楚。

更新:这是Firestore的消息文档的屏幕截图。

enter image description here

这是我的Message模型类:

class Message(document: DocumentSnapshot) {

    companion object {
        private const val KEY_CONTENT = "content"
        private const val KEY_DATE_CREATED = "dateCreated"
    }

    private lateinit var mId: String
    private lateinit var mContent: String
    private lateinit var mDateCreated: Date

    // TODO: Figuring out why getDate doesn't seem to work for Rooms

    init {
        if (document.exists()) {
            mId = document.id
            mContent = document.getString(KEY_CONTENT)!!
            mDateCreated = document.getDate(KEY_DATE_CREATED)!!
        }
    }

    fun getId(): String = mId

    fun getContent(): String = mContent

    fun getDateCreated(): Date = mDateCreated

    fun getStringFormattedDateCreated() = FormatterUtil.getFormattedTimestamp(mDateCreated)

}

使?的日期可为空(Room)不会做任何事情。

3 个答案:

答案 0 :(得分:0)

似乎没有正确解析日期的格式。

使用firebase我正在做的是将日期转换为Unix时间戳值,将该值存储在firebase中。 你可以用getTime()方法做到这一点。

当我检索数据时,我将Unix时间戳值转换为Date类型。

Date date = new Date((long)timeStamp*1000);

前:

数据------&gt; Unix时间戳

05/14/2018 @ 3:26 pm(UTC)------&gt; 1526311610

答案 1 :(得分:0)

如果我已正确理解此问题,那么您需要设置快照选项,否则您可能无法等待完整结果。

我使用Node.js平台,因此您需要为SDK执行等效操作。

  

如果设置,则控制尚未设置的服务器时间戳的返回值   但已被设定为最终价值。

     

通过指定&#39;估计&#39;,挂起的服务器时间戳返回估计值   基于本地时钟。这个估计值与最终结果不同   一旦服务器结果变为值,就会导致这些值发生变化   可用。

     

通过指定&#39;之前的&#39;,将忽略待处理的时间戳   返回其先前的值。

     

如果省略或设置为&#39; none&#39;,默认情况下将返回null,直到   服务器值可用

以下是Node.js客户端SDK的链接。这可能会帮助您朝着正确的方向前进。 https://firebase.google.com/docs/reference/js/firebase.firestore.SnapshotOptions

答案 2 :(得分:0)

首先,您需要将POJO项目上的名称与数据库中的名称保持一致,示例中的所有POJOs都使用camelCase注释编写并存储在数据库中它不是。

如果您希望将模型与camelCase和数据库保持一致,则可以使用注释PropertyName

data class myFancyPojo(@PropertyName("name") val mName: String = "",
                   @ServerTimestamp
                   @PropertyName("timestamp")
                   val mTimestamp: Date? = null)

您错过了POJO构建器中参数的注释@ServerTimestamp,这标志着它从服务器时间戳中膨胀。

  

用于标记要使用服务器时间戳填充的日期字段的注释。如果正在编写的POJO对于@ ServerTimestamp-annotated字段包含null,则它将替换为服务器生成的时间戳。

https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/ServerTimestamp

最后,不要忘记,如果你用Java编写代码,你应该保留一个空构造函数,如果你在Kotlin上编写代码,你应该为类的任何参数赋予默认值。