英文:
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{}
...
提前谢谢
英文:
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
答案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()
。
如果有人知道更好的选择,请分享
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论