[英]Unable to get Timestamp document field from Firestore
When getting data from Firestore, I am unable to get a timestamp field.从 Firestore 获取数据时,我无法获取时间戳字段。
My Room document is structured like this:我的房间文档的结构如下:
and I'm getting the rooms from Firestore like below.我正在从 Firestore 获取房间,如下所示。
Helper class:助手class:
fun getRooms(userId: String): Task<QuerySnapshot> {
return FirebaseFirestore.getInstance()
.collection(KEY_USERS).document(userId)
.collection(KEY_ROOMS).get()
}
Interactor class:互动者 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
}
My Room
model class:我的Room
model class:
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
}
The issue is that document.getDate(KEY_DATE_CREATED)
is always returning null
.问题是document.getDate(KEY_DATE_CREATED)
总是返回null
。 I've tried using get(KEY_DATE_CREATED)
and getString(KEY_DATE_CREATED)
just to see if I could get any value, but to no avail.我试过使用get(KEY_DATE_CREATED)
和getString(KEY_DATE_CREATED)
只是为了看看我是否可以获得任何价值,但无济于事。
After a few more tries, I tested printing out the whole object and was able to get this:再试几次后,我测试了打印出整个 object 并能够得到这个:
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
}
}
So apparently, the dateCreated
field is not being retrieved in the first place, which explains the null value.显然,首先没有检索到dateCreated
字段,这解释了 null 值。 From the code I have, I believe I'm handling the parsing properly.从我的代码来看,我相信我正在正确处理解析。 What's confusing is I also have a Message
object that has a dateCreated
timestamp field and I'm able to get it properly.令人困惑的是我还有一条Message
object,它有一个dateCreated
时间戳字段,我能够正确地获取它。
PS: The sample codes are in Kotlin, I could post a Java code version if it could help make things more clear. PS:示例代码在Kotlin,我可以发一个Java的代码版本,如果它能帮助更清楚的话。
Update: Here's a screenshot of the Message document from Firestore.更新:这是来自 Firestore 的消息文档的屏幕截图。
And here's the my Message
model class:这是我的Message
model class:
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)
}
Making the Date nullable ( ?
) for Room
does nothing.使Room
的 Date 可为空 ( ?
) 不执行任何操作。
Seems that is not parsing correctly the format of the date. 似乎无法正确解析日期格式。
With firebase what I am doing is convert the date in to an Unix timestamp value, store that value in firebase. 使用firebase,我正在将日期转换为Unix时间戳值,并将该值存储在firebase中。 You can do that with the method getTime(). 您可以使用getTime()方法来实现。
And when I retrieve the data, the same, I convert the Unix timestamp value to a type Date. 当我检索数据时,同样,我将Unix时间戳值转换为类型Date。
Date date = new Date((long)timeStamp*1000);
Ex: 例如:
Data ------> Unix timestamp 数据------> Unix时间戳
05/14/2018 @ 3:26pm (UTC) ------ > 1526311610 2018年5月14日下午3:26(UTC)------> 1526311610
If I have understood this problem correctly then you'll need to set the snapshot options, or it could be you're not waiting for the full result. 如果我已正确理解此问题,则需要设置快照选项,否则可能是您没有等待完整的结果。
I use the Node.js platform so you'll need to do the equivalent for your SDK. 我使用Node.js平台,因此您需要为您的SDK做同样的事情。
If set, controls the return value for server timestamps that have not yet been set to their final value. 如果设置,控制尚未设置为其最终值的服务器时间戳的返回值。
By specifying 'estimate', pending server timestamps return an estimate based on the local clock. 通过指定“估计”,挂起的服务器时间戳返回基于本地时钟的估计。 This estimate will differ from the final value and cause these values to change once the server result becomes available. 此估计值将不同于最终值,并且一旦服务器结果可用,这些值就会更改。
By specifying 'previous', pending timestamps will be ignored and return their previous value instead. 通过指定“ previous”,待处理的时间戳将被忽略,而是返回其先前的值。
If omitted or set to 'none', null will be returned by default until the server value becomes available 如果省略或设置为“ none”,则默认情况下将返回null,直到服务器值可用为止
Here is the link to the Node.js Client SDK. 这是指向Node.js客户端SDK的链接。 This may help you in the right direction. 这可能会帮助您朝正确的方向发展。 https://firebase.google.com/docs/reference/js/firebase.firestore.SnapshotOptions https://firebase.google.com/docs/reference/js/firebase.firestore.SnapshotOptions
First, you need to keep the names on your POJO
item with the same ones of your Database, all your POJOs
in the examples are wrote with camelCase
annotation and in your database it is not. 首先,您需要将POJO
项的名称与数据库中的名称保持相同,示例中的所有POJOs
都使用camelCase
批注编写,而在数据库中则不是。
If you want to keep your model with camelCase
and your database without, you can use the annotation PropertyName
: 如果要使用camelCase
保留模型而没有使用camelCase
保留数据库,则可以使用批注PropertyName
:
data class myFancyPojo(@PropertyName("name") val mName: String = "",
@ServerTimestamp
@PropertyName("timestamp")
val mTimestamp: Date? = null)
You missed the annotation @ServerTimestamp
on your parameter in the POJO builder, which marks it it be inflated from a server timestamp. 您错过了POJO构建器中参数上的注解@ServerTimestamp
,这将其标记为已从服务器时间戳中夸大。
Annotation used to mark a Date field to be populated with a server timestamp. 用于标记要使用服务器时间戳填充的“日期”字段的注释。 If a POJO being written contains null for a @ServerTimestamp-annotated field, it will be replaced with a server-generated timestamp. 如果要写入的POJO包含@ServerTimestamp注释的字段为null,它将被服务器生成的时间戳替换。
https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/ServerTimestamp https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/ServerTimestamp
Finally, don't forget that if you are writing your code in Java you should keep an empty constructor, and if you are writing it on Kotlin you should give a default value to any parameter of the class. 最后,不要忘记,如果您使用Java编写代码,则应保留一个空的构造函数,如果您是在Kotlin上编写,则应为该类的任何参数提供默认值。
When getting timeStamp from document you can use this.从文档中获取时间戳时,您可以使用它。
Object ob=document.getDate("createdDate", DocumentSnapshot.ServerTimestampBehavior.ESTIMATE);
And Then> ob.toString();
然后> ob.toString();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.