简体   繁体   English

在 Firestore 文档中添加时间戳

[英]Add timestamp in Firestore documents

I'm newbie to Firestore.我是 Firestore 的新手。 Firestore docs says... Firestore 文档说...

Important : Unlike "push IDs" in the Firebase Realtime Database, Cloud Firestore auto-generated IDs do not provide any automatic ordering.重要提示:与 Firebase 实时数据库中的“推送 ID”不同,Cloud Firestore 自动生成的 ID 不提供任何自动排序。 If you want to be able to order your documents by creation date, you should store a timestamp as a field in the documents.如果您希望能够按创建日期对文档进行排序,您应该将时间戳存储为文档中的一个字段。

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

So do I have to create key name as timestamp in document?那么我是否必须在文档中创建键名作为timestamp Or created is suffice to fulfill above statement from Firestore documentation.created足以满足 Firestore 文档中的上述声明。

{
    "created": 1534183990,
    "modified": 1534183990,
    "timestamp":1534183990
}
firebase.firestore.FieldValue.serverTimestamp()

Whatever you want to call it is fine afaik.无论你想怎么称呼它都很好afaik。 Then you can use orderByChild('created').然后你可以使用 orderByChild('created')。

I also mostly use firebase.database.ServerValue.TIMESTAMP when setting time我在设置时间时也主要使用 firebase.database.ServerValue.TIMESTAMP

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

Use firestore Timestamp class, firebase.firestore.Timestamp.now() .使用 firestore Timestamp 类firebase.firestore.Timestamp.now()

Since firebase.firestore.FieldValue.serverTimestamp() does not work with add method from firestore.由于firebase.firestore.FieldValue.serverTimestamp()不适用于来自 firestore 的add方法。 Reference 参考

For Firestore对于 Firestore

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

REALTIME SERVER TIMESTAMP USING FIRESTORE使用 FIRSTORE 的实时服务器时间戳

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);
            });

}

All you need is to import ' firebase ' and then call firebase.firestore.FieldValue.serverTimestamp() wherever you need it.您只需要导入“ firebase ”,然后在需要的地方调用firebase.firestore.FieldValue.serverTimestamp() 即可 Be careful with the spelling though, its " serverTimestamp() ".不过要小心拼写,它的“ serverTimestamp() ”。 In this example it provides the timestamp value to ' createdAt ' when uploading to the firestore's product's collection.在此示例中,它在上传到 firestore 的产品集合时为“ createdAt ”提供时间戳值。

That's correct, like most database, Firestore doesn't store creation times.没错,就像大多数数据库一样,Firestore 不存储创建时间。 In order to sort objects by time:为了按时间对对象进行排序:

Create the timestamp on the web client (option 1):在 Web 客户端上创建时间戳(选项 1):

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

The big caveat here is that Timestamp.now() uses the local machine time.这里需要注意的是Timestamp.now()使用本地机器时间。 Therefore, if this is run on a client machine, you have no guarantee the timestamp is accurate.因此,如果这是在客户端计算机上运行,​​则无法保证时间戳是准确的。 If you're setting this on the server or if guaranteed order isn't so important, it might be fine.如果您在服务器上设置此设置,或者保证顺序不是那么重要,则可能没问题。

You can also use a timestamp sentinel (usually better):您还可以使用时间戳标记(通常更好):

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

A timestamp sentinel is a token that tells the firestore server to set the time server side on first write.时间戳标记是一个令牌,它告诉 Firestore 服务器在第一次写入时设置时间服务器端。

You might notice that I used doc().set() .您可能会注意到我使用了doc().set() This is equivalent to add() .这相当于add() Officially, FieldValues only support set() and update().正式地,FieldValues 只支持 set() 和 update()。

Also, if you read the sentinel before it is written (eg, in a listener) it will be NULL unless you read the document like this:此外,如果您在写入之前阅读哨兵(例如,在侦听器中)它将为 NULL,除非您像这样阅读文档:

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

Set up your query with something like this:使用以下内容设置您的查询:

// 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);

Note that this query uses the local machine time ( Timestamp.now() ).请注意,此查询使用本地机器时间( Timestamp.now() )。 If it's really important that your app uses the correct time on the clients, you could utilize this feature of Firebase's Realtime Database:如果您的应用在客户端上使用正确的时间真的很重要,您可以利用 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);

The documentation isn't suggesting the names of any of your fields.该文档并未建议您的任何字段的名称。 The part you're quoting is just saying two things:你引用的部分只是说两件事:

  1. The automatically generated document IDs for Firestore don't have a natural time-based ordering like they did in Realtime Database. Firestore 自动生成的文档 ID 不像在实时数据库中那样具有基于时间的自然排序。
  2. If you want time-based ordering, store a timestamp in the document, and use that to order your queries.如果您想要基于时间的排序,请在文档中存储一个时间戳,并使用它来排序您的查询。 (You can call it whatever you want.) (你可以随意称呼它。)

This solution worked for me:这个解决方案对我有用:

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

The result in Cloud Firestore is: Cloud Firestore Result Cloud Firestore 中的结果是: Cloud Firestore Result

Try this one for Swift 4 Timestamp(date: Date())试试这个 Swift 4 Timestamp(date: 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!")
}
}

The way it worked with me, is just taking the timestamp from the snapshot parameter snapshot.updateTime它与我合作的方式只是从快照参数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);
});

}); });

I am using Firestore to store data that comes from a Raspberry PI with Python.我正在使用 Firestore 存储来自带有 Python 的 Raspberry PI 的数据。 The pipeline is like this:管道是这样的:

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

Data in the device is a Python Dictionary.设备中的数据是一个 Python 字典。 I convert that to JSON.我将其转换为 JSON。 The problem I had was that paho-mqtt will only send (publish) data as String and one of the fields of my data is timestamp.我遇到的问题是 paho-mqtt 只会将数据作为字符串发送(发布),而我的数据字段之一是时间戳。 This timestamp is saved from the device because it accurately says when the measurement was taken regardless on when the data is ultimately stored in the database.该时间戳从设备中保存,因为它准确地说明了何时进行测量,而不管数据最终何时存储在数据库中。

When I send my JSON structure, Firestore will store my field 'timestamp' as String.当我发送 JSON 结构时,Firestore 会将我的字段“时间戳”存储为字符串。 This is not convenient.这不方便。 So here is the solution.所以这是解决方案。

I do a conversion in the Cloud Function that is triggered by the Pub/Sub to write into Firestore using Moment library to convert.我在 Cloud Function 中进行了一个由 Pub/Sub 触发的转换,以使用 Moment 库写入 Firestore 进行转换。

Note: I am getting the timestamp in python with:注意:我在 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;  
});

Firestone method does not work.火石方法不起作用。 Use Timestamp from java.sql.Timestamp and don't cast to string.. Then firestone formats it properly.使用 java.sql.Timestamp 中的 Timestamp 并且不要转换为字符串.. 然后 firestone 正确格式化它。 For example to mark a now() use:例如标记 now() 使用:

val timestamp = Timestamp(System.currentTimeMillis())

multiple ways to store time in Firestore在 Firestore 中存储时间的多种方式

  1. firebaseAdmin.firestore.FieldValue.serverTimestamp() method. firebaseAdmin.firestore.FieldValue.serverTimestamp()方法。 The actual timestamp will be computed when the doc is written to the Firestore.将文档写入 Firestore 时将计算实际时间戳。
    while storing it looks like this:存储时它看起来像这样:

在此处输入图片说明

  1. firebaseAdmin.firestore.Timestamp.now() method. firebaseAdmin.firestore.Timestamp.now()方法。
    while storing it looks like this:存储时它看起来像这样:

在此处输入图片说明

For both the methods, next time you fetch data it will return Firestore Timestamp object:对于这两种方法,下次获取数据时,它将返回 Firestore Timestamp 对象:

在此处输入图片说明

So, you first need to convert it to native js Date object and then you can perform methods on it like toISOString() .因此,您首先需要将其转换为原生 js Date对象,然后您可以对其执行方法,例如toISOString()

export function FStimestampToDate(
  timestamp:
    | FirebaseFirestore.Timestamp
    | FirebaseFirestore.FieldValue
): Date {
  return (timestamp as FirebaseFirestore.Timestamp).toDate();
}
  1. Store as unix timestamp Date.now , it'll be stored as number ie 1627235565028 but you won't be able to see it as readable Date in firestore db.存储为 unix 时间戳Date.now ,它将存储为数字,即1627235565028但您将无法在 firestore db 中将其视为可读日期。
    To query on this Firestore field, you need to convert the date to timestamp and then query.要查询此 Firestore 字段,您需要将日期转换为时间戳,然后进行查询。

  2. Store as new Date().toISOString() ie "2021-07-25T17:56:40.373Z" but you won't be able to perform date range query on this.存储为new Date().toISOString()"2021-07-25T17:56:40.373Z"但您将无法对此执行日期范围查询。

I prefer the 2nd or 3rd way.我更喜欢第二种或第三种方式。

According to the docs , you can "set a field in your document to a server timestamp which tracks when the server receives the update".根据文档,您可以“将文档中的一个字段设置为服务器时间戳,用于跟踪服务器何时收到更新”。

Example:例子:

import { updateDoc, serverTimestamp } from "firebase/firestore";

const docRef = doc(db, 'objects', 'some-id');

// Update the timestamp field with the value from the server
const updateTimestamp = await updateDoc(docRef, {
    timestamp: serverTimestamp() // this does the trick!
});

Sharing what worked for me after googling for 2 hours, for firebase 9+谷歌搜索 2 小时后分享对我有用的内容,适用于 firebase 9+

import { serverTimestamp } from "firebase/firestore";

export const postData = ({ name, points }: any) => {
  const scoresRef = collection(db, "scores");
  return addDoc(scoresRef, {
    name,
    points
    date: serverTimestamp(),
  });
};

Swift 5.1斯威夫特 5.1

...
"dateExample": Timestamp(date: Date()),
...

The newest version from Firestore you should use it as follow来自 Firestore 的最新版本你应该使用它如下

import { doc, setDoc, Timestamp } from "firebase/firestore"; 

const docData = {
    ...
    dateExample: Timestamp.fromDate(new Date("December 10, 1815"))
};
await setDoc(doc(db, "data", "one"), docData);

or for sever timestamp或服务器时间戳

import { updateDoc, serverTimestamp } from "firebase/firestore";

const docRef = doc(db, 'objects', 'some-id');

const updateTimestamp = await updateDoc(docRef, {
   timestamp: serverTimestamp()
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM