在Firestore文档中添加时间戳

时间:2018-08-14 17:33:03

标签: firebase google-cloud-firestore

我是Firestore的新手。 Firestore文档说...

  

重要:与Firebase实时数据库中的“推送ID”不同,Cloud Firestore自动生成的ID不提供任何自动排序。如果您希望能够按创建日期排序文档,请将时间戳记存储为文档中的字段。

参考:https://firebase.google.com/docs/firestore/manage-data/add-data

那么我是否必须在文档中将键名创建为timestamp?或者created足以满足Firestore文档中的上述要求。

{
    "created": 1534183990,
    "modified": 1534183990,
    "timestamp":1534183990
}

13 个答案:

答案 0 :(得分:5)

使用 FIRESTORE 的实时服务器时间戳

import firebase from "firebase/app";

const someFunctionToUploadProduct = () => {

       firebase.firestore().collection("products").add({
                name: name,
                price : price,
                color : color,
                weight :weight,
                size : size,
                createdAt : firebase.firestore.FieldValue.serverTimestamp()
            })
            .then(function(docRef) {
                console.log("Document written with ID: ", docRef.id);
            })
            .catch(function(error) {
                console.error("Error adding document: ", error);
            });

}

您只需要导入“firebase”然后调用 firebase.firestore.FieldValue.serverTimestamp() 无论您需要什么。不过要小心拼写,它的“serverTimestamp()”。在此示例中,它在上传到 Firestore 的产品集合时向“createdAt”提供时间戳值。

答案 1 :(得分:2)

任何您想称呼的都很好。然后,您可以使用orderByChild('created')。

设置时间时,我也大多使用firebase.database.ServerValue.TIMESTAMP

ref.child(key).set({
  id: itemId,
  content: itemContent,
  user: uid,
  created: firebase.database.ServerValue.TIMESTAMP 
})

答案 2 :(得分:2)

此解决方案对我有用:

Firestore.instance.collection("collectionName").add({'created': Timestamp.now()});

Cloud Firestore中的结果是: Cloud Firestore Result

答案 3 :(得分:2)

没错,就像大多数数据库一样,Firestore 不存储创建时间。为了按时间对对象进行排序:

在 Web 客户端上创建时间戳(选项 1):

db.collection("messages").doc().set({
  ....
  createdAt: firebase.firestore.Timestamp.now()
})

这里的重要警告是Timestamp.now()使用本地机器时间。因此,如果这是在客户端机器上运行,您不能保证时间戳是准确的。如果您在服务器上设置此项,或者保证顺序不是那么重要,那么可能没问题。

您还可以使用时间戳标记(通常更好):

db.collection("messages").doc().set({
  ....
  createdAt: firebase.firestore.FieldValue.serverTimestamp()
})

时间戳标记是一个令牌,它告诉 Firestore 服务器在第一次写入时设置时间服务器端。

您可能会注意到我使用了 doc().set()。这相当于 add()。正式地,FieldValues 只支持 set() 和 update()。

此外,如果您在写入之前阅读哨兵(例如,在侦听器中),除非您像这样阅读文档,否则它将为 NULL:

doc.data({ serverTimestamps: 'estimate' })

使用以下内容设置您的查询:

// quick and dirty way, but uses local machine time
const midnight = new Date(firebase.firestore.Timestamp.now().toDate().setHours(0, 0, 0, 0));

const todaysMessages = firebase
  .firestore()
  .collection(`users/${user.id}/messages`)
  .orderBy('createdAt', 'desc')
  .where('createdAt', '>=', midnight);

请注意,此查询使用本地机器时间 (Timestamp.now())。如果您的应用在客户端上使用正确的时间真的很重要,您可以利用 Firebase 的实时数据库的此功能:

const serverTimeOffset = (await firebase.database().ref('/.info/serverTimeOffset').once('value')).val();
const midnightServerMilliseconds = new Date(serverTimeOffset + Date.now()).setHours(0, 0, 0, 0);
const midnightServer = new Date(midnightServerMilliseconds);

答案 4 :(得分:1)

文档中没有建议您使用任何字段的名称。您引用的部分只是说两件事:

  1. 自动为Firestore生成的文档ID不像在实时数据库中那样具有自然的基于时间的排序。
  2. 如果要基于时间的排序,请在文档中存储一个时间戳,然后使用该时间戳对查询进行排序。 (您可以随便叫它。)

答案 5 :(得分:1)

对于Firestore

ref.doc(key).set({
  created: firebase.firestore.FieldValue.serverTimestamp()
})

答案 6 :(得分:0)

尝试使用Swift 4时间戳(日期:Date())

let docData: [String: Any] = [
"stringExample": "Hello world!",
"booleanExample": true,
"numberExample": 3.14159265,
"dateExample": Timestamp(Date()),
"arrayExample": [5, true, "hello"],
"nullExample": NSNull(),
"objectExample": [
    "a": 5,
    "b": [
        "nested": "foo"
    ]
]
]
db.collection("data").document("one").setData(docData) { err in
if let err = err {
    print("Error writing document: \(err)")
} else {
    print("Document successfully written!")
}
}

答案 7 :(得分:0)

它与我合作的方式只是从快照参数 snapshot.updateTime

中获取时间戳。
exports.newUserCreated = functions.firestore.document('users/{userId}').onCreate(async (snapshot, context) => {
console.log('started!     v1.7');
const userID = context.params['userId'];

firestore.collection(`users/${userID}/lists`).add({
    'created_time': snapshot.updateTime,
    'name':'Products I ♥',
}).then(documentReference => {
    console.log("initial public list created");
    return null;
  }).catch(error => {
    console.error('Error creating initial list', error);
    process.exit(1);
});

});

答案 8 :(得分:0)

Swift 5.1

public void reconnect() {
    reset();
    connect();
}

private void reset() {
    Thread current = Thread.currentThread();
    if (current == writeThread || current == connectReadThread) {
        throw new IllegalStateException("You cannot initialize a reconnect out of the WebSocket thread. Use reconnect in another thread to insure a successful cleanup.");
    }
...
}

答案 9 :(得分:0)

使用firestore时间戳类firebase.firestore.Timestamp.now()

由于firebase.firestore.FieldValue.serverTimestamp()不适用于Firestore中的add方法。 Reference

答案 10 :(得分:0)

我正在使用Firestore存储来自带有Python的Raspberry PI的数据。管道是这样的:

Raspberry PI(使用paho-mqtt的Python)-> Google Cloud IoT-> Google Cloud Pub / Sub-> Firebase Functions-> Firestore。

设备中的数据是Python字典。我将其转换为JSON。 我遇到的问题是paho-mqtt将仅以String形式发送(发布)数据,而我的数据字段之一是时间戳。该时间戳是从设备中保存的,因为它可以准确说明何时进行测量,而与最终将数据存储在数据库中的时间无关。

当我发送JSON结构时,Firestore会将字段“时间戳”存储为String。这不方便。所以这是解决方案。

我在Cloud Function中进行了转换,该转换由Pub / Sub触发,并使用Moment库进行转换以写入Firestore。

注意:我正在使用以下命令获取python中的时间戳:

currenttime = datetime.datetime.utcnow()

var moment = require('moment'); // require Moment 
function toTimestamp(strDate){
  return parsedTime = moment(strDate, "YYYY-MM-DD HH:mm:ss:SS");
 }

exports.myFunctionPubSub = functions.pubsub.topic('my-topic-name').onPublish((message, context) => {

  let parsedMessage = null;
  try {
    parsedMessage = message.json;

    // Convert timestamp string to timestamp object
    parsedMessage.date = toTimestamp(parsedMessage.date);

    // Get the Device ID from the message. Useful when you have multiple IoT devices
    deviceID = parsedMessage._deviceID;

    let addDoc = db.collection('MyDevices')
                    .doc(deviceID)
                    .collection('DeviceData')
                    .add(parsedMessage)
                    .then ( (ref) => {
                      console.log('Added document ID: ', ref.id);
                      return null;
                    }).catch ( (error) => {
                      console.error('Failed to write database', error);
                      return null;
                    });

  } catch (e) {
    console.error('PubSub message was not JSON', e);
  } 

  // // Expected return or a warning will be triggered in the Firebase Function logs.
  return null;  
});

答案 11 :(得分:0)

Fire石方法不起作用。使用java.sql.Timestamp中的Timestamp,不要将其强制转换为字符串。然后,firestone将其正确格式化。例如,标记一个now()使用:

val timestamp = Timestamp(System.currentTimeMillis())

答案 12 :(得分:0)

在 Firestore 中存储时间的多种方式

  1. firebaseAdmin.firestore.FieldValue.serverTimestamp() 方法。将文档写入 Firestore 时将计算实际时间戳。
    存储时它看起来像这样:

enter image description here

  1. firebaseAdmin.firestore.Timestamp.now() 方法。
    存储时它看起来像这样:

enter image description here

对于这两种方法,下次获取数据时,它将返回 Firestore Timestamp 对象:

enter image description here

因此,您首先需要将其转换为原生 js Date 对象,然后您可以像 toISOString() 一样对其执行方法。

export function FStimestampToDate(
  timestamp:
    | FirebaseFirestore.Timestamp
    | FirebaseFirestore.FieldValue
): Date {
  return (timestamp as FirebaseFirestore.Timestamp).toDate();
}
  1. 存储为 unix 时间戳 Date.now,它将存储为数字,即 1627235565028,但您将无法在 firestore db 中将其视为可读日期。
    要查询这个 Firestore 字段,您需要将日期转换为时间戳,然后再查询。

  2. 存储为 new Date().toISOString()"2021-07-25T17:56:40.373Z",但您将无法对此执行日期范围查询。

我更喜欢第二种或第三种方式。