云函数Firestore触发器使用不准确的数字字段的文档。

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

Cloud Function Firestore Trigger with document using inaccurate number fields

问题

我正在使用GoLang实现一个Firestore触发器,它将监听集合上的更改,并在另一个集合上创建一个新文档。

到目前为止,我已经查看了官方文档,链接在这里:https://cloud.google.com/functions/docs/calling/cloud-firestore#event_structure,其中提供了一个示例,展示了如何使用自定义结构体(在这里表示为MyData):

// FirestoreValue holds Firestore fields.
type FirestoreValue struct {
        CreateTime time.Time `json:"createTime"`
        // Fields is the data for this value. The type depends on the format of your
        // database. Log an interface{} value and inspect the result to see a JSON
        // representation of your database fields.
        Fields     MyData    `json:"fields"`
        Name       string    `json:"name"`
        UpdateTime time.Time `json:"updateTime"`
}

// MyData represents a value from Firestore. The type definition depends on the
// format of your database.
type MyData struct {
        Original struct {
                StringValue string `json:"stringValue"`
        } `json:"original"`
}

这部分工作得很好。
现在问题变得棘手的地方是,如果我们的文档中有一个数字而不是字符串,就像这样:

type MyOtherData struct {
        Original struct {
                DoubleValue float64 `json:"doubleValue"`
        } `json:"original"`
}

一切似乎都很好,实际上也是可以工作的,但只有当文档中的数字有小数部分时,比如1.2。然而,如果这个文档恰好有一个没有小数部分的值,比如1,那么这个数字在被解码为MyOtherData时会变成0

编辑:

好的,现在我明白为什么是0了,因为实际上,Firestore并不区分整数和浮点数,这使得对象以以下方式(以JSON格式)传递:

"fields":{"original":{"doubleValue":3.5}

如果文档的值有小数部分。
但是,如果文档没有小数部分,则以以下方式传递:

"fields":{"original":{"integerValue":"3"}

有人知道应该如何优雅地处理这个问题吗?
我希望避免在这种情况下使用interface{}...

提前谢谢 云函数Firestore触发器使用不准确的数字字段的文档。

英文:

I'm implementing a firestore trigger in GoLang, which will listen to changes on a collection and with, will create a new document on a different collection.

So far so good, I had a look into the official documentation here: https://cloud.google.com/functions/docs/calling/cloud-firestore#event_structure which gives an example on how we can use a custom sruct (here represented as MyData) like so:

// FirestoreValue holds Firestore fields.
type FirestoreValue struct {
        CreateTime time.Time `json:"createTime"`
        // Fields is the data for this value. The type depends on the format of your
        // database. Log an interface{} value and inspect the result to see a JSON
        // representation of your database fields.
        Fields     MyData    `json:"fields"`
        Name       string    `json:"name"`
        UpdateTime time.Time `json:"updateTime"`
}

// MyData represents a value from Firestore. The type definition depends on the
// format of your database.
type MyData struct {
        Original struct {
                StringValue string `json:"stringValue"`
        } `json:"original"`
}

And that works fine.
Now where it gets trickier is if our document has a number instead of a string, like:

type MyOtherData struct {
        Original struct {
                DoubleValue float64 `json:"doubleValue"`
        } `json:"original"`
}

Everything seems fine, and in fact it works, but only if the document has a number with a decimal part, like: 1.2. However, if this document happens to have a value without decimal part, like: 1, then the number comes decoded to MyOtherData as 0.

Edited:

Ok, now I get why it's 0, because in fact, firestore doesn't distinguish between integer and float, and that makes the object coming with (in json):

"fields":{"original":{"doubleValue":3.5}

if the document has a value with a decimal part.
But comes with:

"fields":{"original":{"integerValue":"3"}

if the document has no decimal part.

Does anyone knows how should this be handled elegantly?
I would like to avoid using interface{} for this cases...

Thanks in advance 云函数Firestore触发器使用不准确的数字字段的文档。

答案1

得分: 1

所以,我找到的更好的选择是将我的结构体改成这样:

type MyOtherData struct {
	Original FirestoreNumber `json:"original"`
}

type FirestoreNumber struct {
	DoubleValue  float64 `json:"doubleValue"`
	IntegerValue int     `json:"integerValue,string"`
}

func (fn *FirestoreNumber) Value() float64 {
	if fn.IntegerValue != 0 {
		return float64(fn.IntegerValue)
	}

	return fn.DoubleValue
}

然后,不再直接访问 myOtherData.Original.DoubleValue,而是使用 myOtherData.Original.Value()

如果有人知道更好的选择,请分享 云函数Firestore触发器使用不准确的数字字段的文档。

英文:

So, the better option I found was to change my struct like this:

type MyOtherData struct {
        Original FirestoreNumber `json:"original"`
}

type FirestoreNumber struct {
	DoubleValue  float64 `json:"doubleValue"`
	IntegerValue int     `json:"integerValue,string"`
}

func (fn *FirestoreNumber) Value() float64 {
	if fn.IntegerValue != 0 {
		return float64(fn.IntegerValue)
	}

	return fn.DoubleValue
}

Then, instead of accessing directly myOtherData.Original.DoubleValue, I do myOtherData.Original.Value()

If someone knows a better option, please share 云函数Firestore触发器使用不准确的数字字段的文档。

huangapple
  • 本文由 发表于 2022年11月8日 01:35:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/74350652.html
匿名

发表评论

匿名网友

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

确定