Ari
Ari

Reputation: 6159

How to get and store the document ID using a struct

I've defined a data structure like so:

type Person struct {
    Name string `firestore:"name,omitempty"`
}

When I query all the documents in a collection I'd like to be able to attach the ID to the documents for later reference, but not necessarily have ID as an attribute stored in Firestore (unless its the only way). In javascript or python this is straightforward as the data structures are dynamic and I can just query the ID post get() and add it as a dynamic key/value. myObj.id = doc.id

How would I do this with Go?

package main

import (
    "fmt"
    "cloud.google.com/go/firestore"
    "context"
    "google.golang.org/api/iterator"
    "log"
)

type Person struct {
    Name string `firestore:"name,omitempty"`
}

func main() {
    ctx := context.Background()

    c, err := firestore.NewClient(ctx, "my-project")
    if err != nil {
        log.Fatalf("error: %v",  err)
    }
    
    var people []Person
    
    iter := c.Collection("people").Documents(ctx)
    for {
        doc, err := iter.Next()
        if err == iterator.Done {
            break
        }
        if err != nil {
            log.Fatalf("error: %v",  err)
        }

        var p Person
        err = doc.DataTo(p)
        if err != nil {
            log.Fatalf("error: %v",  err)
        }
        // id := doc.Ref.ID
        people = append(people, p)
    }

    fmt.Println(people)
}

output, no ID

>> [{John Smith}]

Upvotes: 0

Views: 977

Answers (2)

Rafael FT
Rafael FT

Reputation: 115

If you want to store the firestore document ID on the Person type, your struct must have a declared field for it.

Golang firestore docs don't mention this explicitly, but since a firestore doc ID is not part of the document fields, the func (*DocumentSnapshot) DataTo does not populate the ID. Instead, you may get the document ID from the DocumentRef type and add it to Person yourself.

The doc also states that:

Note that this client supports struct tags beginning with "firestore:" that work like the tags of the encoding/json package, letting you rename fields, ignore them, or omit their values when empty

Therefore, if you want to omit the ID when marshaling back for firestore, your could use the tag firestore:"-"

The Person would look like this:

type Person struct {
    ID   string `firestore:"-"`
    Name string `firestore:"name,omitempty"`
}

inside the loop:

var p Person
err := docSnap.DataTo(&p)
if err != nil {
    // handle it
}
p.ID = doc.Ref.ID

Upvotes: 1

Gari Singh
Gari Singh

Reputation: 12033

I believe that the firestore struct tags works the same way as the tags in the encoding/json package. So a tag with a value of "-" would mean ignore the field. So

type Person struct {
    ID   int `firestore:"-"`
    Name string `firestore:"name,omitempty"`
}

should do the trick.

You can set ID yourself, but the firestore pkg will ignore it when reading/writing data.

Upvotes: 2

Related Questions