首頁  >  文章  >  後端開發  >  我是否需要額外往返 firestore 來讀取建立和更新的時間戳欄位?

我是否需要額外往返 firestore 來讀取建立和更新的時間戳欄位?

PHPz
PHPz轉載
2024-02-11 18:36:091193瀏覽

我是否需要额外往返 firestore 来读取创建和更新的时间戳字段?

在使用Firestore時,你可能會懷疑是否需要額外的往返作業來讀取建立和更新的時間戳欄位。答案是不需要。 Firestore會自動為每個文件提供建立和更新時間戳,你可以透過引用這些欄位來取得對應的時間資訊。這樣,你就不需要額外的操作來讀取時間戳字段,可以更便捷地獲取到文檔的創建和更新時間。這樣的設計使得在開發過程中更有效率和簡化,避免了不必要的程式碼和請求。

問題內容

  1. #好的,我在 go 中有一個 rest api ,它使用 firestore 儲存 ticket 資源。為此,我使用:firestore go client

  2. 我希望能夠透過 date 建立/更新日期 對我的文檔進行排序,因此按照文檔,我將這 2 個欄位作為時間戳記儲存在文檔中。

  3. 我在這兩個欄位上使用標籤 servertimestamp 。透過這樣做,該值應該是 firestore 伺服器處理請求的時間。

  4. 更新操作的 http 回應應包含以下正文:

{
 "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"
 }
}

這表示在我更新票證文件後,除了更新的 title 或 price 之外,我還需要更新 date_updated 欄位的值。

目前可行,但我很好奇我編碼的方式是否就是這樣做的方式。正如您在程式碼範例中看到的,我使用交易來更新票證。除了再次讀取更新的票證之外,我沒有找到檢索 dateupdated 欄位的更新值的方法。

域實體定義如下:

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
    }

)

我將在此處附加從創建和更新角度與 firestore 的通信:

// 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,
    }
}

解決方法

如果我理解正確的話,DateUpdated欄位是一個伺服器端時間戳,這意味著它的值是由伺服器在將該值寫入存儲層時確定的(即所謂的字段轉換)。由於 Firestore SDK 中的寫入操作不會傳回該操作的結果數據,因此將該值傳回應用程式中的唯一方法實際上是在寫入後執行額外的讀取操作來取得它。

SDK 不會自動執行此讀取,因為這是一個收費操作,很多情況下是不需要的。因此,透過讓您的程式碼來執行該讀取,您可以決定是否產生此成本。

以上是我是否需要額外往返 firestore 來讀取建立和更新的時間戳欄位?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除