How to get and store the document ID using a struct

huangapple go评论85阅读模式
英文:

How to get and store the document ID using a struct

问题

我已经定义了一个类似这样的数据结构:

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

当我查询集合中的所有文档时,我希望能够将ID附加到文档上以供以后引用,但不一定要将ID作为存储在Firestore中的属性(除非这是唯一的方法)。在JavaScript或Python中,这很简单,因为数据结构是动态的,我只需在get()之后查询ID并将其添加为动态键/值。myObj.id = doc.id

那么在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)
}

输出,没有ID

>> [{John Smith}]
英文:

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}]

答案1

得分: 2

我相信firestore结构标签的工作方式与encoding/json包中的标签相同。因此,值为"-"的标签意味着忽略该字段。

所以,下面的代码应该可以实现:

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

你可以自己设置ID的值,但是在读取/写入数据时,firestore包将忽略它。

英文:

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.

答案2

得分: 1

如果你想在Person类型上存储Firestore文档的ID,你的结构体必须声明一个字段来存储它。

Golang firestore文档没有明确提到这一点,但由于Firestore文档ID不是文档字段的一部分,func (*DocumentSnapshot) DataTo不会填充ID。相反,你可以从DocumentRef类型获取文档ID,并将其添加到Person中。

文档还指出:
> 请注意,此客户端支持以“firestore:”开头的结构标签,其工作方式类似于encoding/json包的标签,允许您重命名字段、忽略它们或在为空时省略它们的值。

因此,如果你想在将数据编组回Firestore时省略ID,可以使用标签firestore:"-"

Person的结构如下所示:

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

在循环内部:

var p Person
err := docSnap.DataTo(&p)
if err != nil {
    // 处理错误
}
p.ID = doc.Ref.ID
英文:

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

huangapple
  • 本文由 发表于 2021年8月21日 14:24:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/68870654.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定