Bei der Verwendung von Firestore fragen Sie sich möglicherweise, ob zusätzliche Roundtrips erforderlich sind, um die erstellten und aktualisierten Zeitstempelfelder zu lesen. Die Antwort ist nein. Firestore stellt automatisch Erstellungs- und Aktualisierungszeitstempel für jedes Dokument bereit, und Sie können die entsprechenden Zeitinformationen erhalten, indem Sie auf diese Felder verweisen. Auf diese Weise sind keine zusätzlichen Vorgänge zum Lesen des Zeitstempelfelds erforderlich und Sie können die Erstellungs- und Aktualisierungszeit des Dokuments einfacher ermitteln. Dieses Design macht den Entwicklungsprozess effizienter und vereinfacht und vermeidet unnötigen Code und Anfragen.
Okay, hier bin ich go
中有一个 rest api
,它使用 firestore
存储 ticket
Ressourcen. Hierfür verwende ich: Firestore Go Client
Ich möchte meine Dokumente nach date 创建/更新日期
sortieren können, also speichere ich je nach Dokument diese beiden Felder als Zeitstempel im Dokument.
Ich verwende das Etikett servertimestamp
auf beiden Feldern. Dabei sollte der Wert die Zeit sein, die der Firestore-Server benötigt hat, um die Anfrage zu verarbeiten.
Die http-Antwort für den Aktualisierungsvorgang sollte den folgenden Text enthalten:
{ "ticket": { "id": "af41766e-76ea-43b5-86c1-8ba382edd4dc", "title": "ticket updated title", "price": 9, "date_created": "2023-01-06 09:07:24", "date_updated": "2023-01-06 10:08:24" } }
Das bedeutet, dass nach dem Aktualisieren des Ticketdokuments nichts anderes als der Wert des aktualisierten Feldes title 或 price
之外,我还需要更新 date_updated
angezeigt wird.
Im Moment funktioniert es, aber ich bin gespannt, ob die Art und Weise, wie ich programmiere, dafür geeignet ist. Wie Sie im Codebeispiel sehen können, verwende ich eine Transaktion, um das Ticket zu aktualisieren. Ich finde keine andere Möglichkeit, den aktualisierten Wert des Felds dateupdated
abzurufen, als das aktualisierte Ticket erneut zu lesen.
Domänenentitäten sind wie folgt definiert:
package tixer import ( "context" "time" "github.com/google/uuid" ) type ( // ticketid represents a unique identifier for a ticket. // it's a domain type. ticketid uuid.uuid // ticket represents an individual ticket in the system. // it's a domain type. ticket struct { id ticketid title string price float64 datecreated time.time dateupdated time.time } )
Ich werde die Kommunikation mit Firestore aus der Perspektive der Erstellung und Aktualisierung hier anhängen:
// Storer persists tickets in Firestore. type Storer struct { client *firestore.Client } func NewStorer(client *firestore.Client) *Storer { return &Storer{client} } func (s *Storer) CreateTicket(ctx context.Context, ticket *tixer.Ticket) error { writeRes, err := s.client.Collection("tickets").Doc(ticket.ID.String()).Set(ctx, createTicket{ Title: ticket.Title, Price: ticket.Price, }) // In this case writeRes.UpdateTime is the time the document was created. ticket.DateCreated = writeRes.UpdateTime return err } func (s *Storer) UpdateTicket(ctx context.Context, ticket *tixer.Ticket) error { docRef := s.client.Collection("tickets").Doc(ticket.ID.String()) err := s.client.RunTransaction(ctx, func(ctx context.Context, tx *firestore.Transaction) error { doc, err := tx.Get(docRef) if err != nil { switch { case status.Code(err) == codes.NotFound: return tixer.ErrTicketNotFound default: return err } } var t persistedTicket if err := doc.DataTo(&t); err != nil { return err } t.ID = doc.Ref.ID if ticket.Title != "" { t.Title = ticket.Title } if ticket.Price != 0 { t.Price = ticket.Price } return tx.Set(docRef, updateTicket{ Title: t.Title, Price: t.Price, DateCreated: t.DateCreated, }) }) if err != nil { return err } updatedTicket, err := s.readTicket(ctx, ticket.ID) if err != nil { return err } *ticket = updatedTicket return nil } func (s *Storer) readTicket(ctx context.Context, id tixer.TicketID) (tixer.Ticket, error) { doc, err := s.client.Collection("tickets").Doc(id.String()).Get(ctx) if err != nil { switch { case status.Code(err) == codes.NotFound: return tixer.Ticket{}, tixer.ErrTicketNotFound default: return tixer.Ticket{}, err } } var t persistedTicket if err := doc.DataTo(&t); err != nil { return tixer.Ticket{}, err } t.ID = doc.Ref.ID return toDomainTicket(t), nil } type ( // persistedTicket represents a stored ticket in Firestore. persistedTicket struct { ID string `firestore:"id"` Title string `firestore:"title"` Price float64 `firestore:"price"` DateCreated time.Time `firestore:"dateCreated"` DateUpdated time.Time `firestore:"dateUpdate"` } // createTicket contains the data needed to create a Ticket in Firestore. createTicket struct { Title string `firestore:"title"` Price float64 `firestore:"price"` DateCreated time.Time `firestore:"dateCreated,serverTimestamp"` DateUpdated time.Time `firestore:"dateUpdate,serverTimestamp"` } // updateTicket contains the data needed to update a Ticket in Firestore. updateTicket struct { Title string `firestore:"title"` Price float64 `firestore:"price"` DateCreated time.Time `firestore:"dateCreated"` DateUpdated time.Time `firestore:"dateUpdate,serverTimestamp"` } ) func toDomainTicket(t persistedTicket) tixer.Ticket { return tixer.Ticket{ ID: tixer.TicketID(uuid.MustParse(t.ID)), Title: t.Title, Price: t.Price, DateCreated: t.DateCreated, DateUpdated: t.DateUpdated, } }
Wenn ich das richtig verstehe, ist das DateUpdated
-Feld ein serverseitiger Zeitstempel, was bedeutet, dass sein Wert vom Server bestimmt wird, wenn er den Wert in die Speicherschicht schreibt (sog. Feldtransformation). Da ein Schreibvorgang im Firestore SDK nicht die Ergebnisdaten des Vorgangs zurückgibt, besteht die einzige Möglichkeit, diesen Wert wieder in die Anwendung zu übertragen, darin, nach dem Schreibvorgang einen zusätzlichen Lesevorgang durchzuführen, um ihn abzurufen.
Das SDK führt diesen Lesevorgang nicht automatisch durch, da es sich um einen kostenpflichtigen Vorgang handelt, der in vielen Fällen nicht benötigt wird. Indem Sie Ihren Code diesen Lesevorgang durchführen lassen, können Sie entscheiden, ob Ihnen diese Kosten entstehen.
Das obige ist der detaillierte Inhalt vonBenötige ich einen zusätzlichen Roundtrip zum Firestore, um die erstellten und aktualisierten Zeitstempelfelder zu lesen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!