英文:
What is the fastest way to decode a nested MongoDB document array into a struct slice in Go?
问题
这是我的问题。我正在使用gqlgen库运行一个GraphQL服务器。在我的数据库中,我有一个类似于这样的MongoDB文档:
{
"_id": ObjectID(...),
"somefield": "data",
"anArrayOfObjects": [
{
"field1": "value1",
"field2": "value2"
},
...
]
}
我想要的是只解码字段anArrayOfObjects
为一个切片(可能看起来像[]MyObj
,其中MyObj
是一个结构体)。
(为了一点背景,我只想要这个字段,因为数组非常大,并且它有自己的GraphQL解析器)。
这是我目前尝试过的:
ObjectID, err := primitive.ObjectIDFromHex("someid")
// 进行一些错误检查
opts := options.FindOne().SetProjection(
bson.D{{Key: "anArrayOfObjects", Value: 1}, {Key: "_id", Value: 0}},
)
myslice = []MyObj{}
err := coll.FindOne(ctx, bson.M{"_id": ObjectID}, opts).Decode(&myslice)
// 错误为"无法将文档解码为[]MyObj"
如果我运行
result = primitive.D{} // 或 primitive.M{}
err := coll.FindOne(ctx, bson.M{"_id": ObjectID}, opts).Decode(&result)
// 错误为nil,result包含了我想要的一切,但不是在"理想"的数据结构中
通过后者,我可以遍历result
然后将所有内容映射到每个结构字段(类似于这个答案)。但我的直觉告诉我,可能有比这更好的方法。
提前感谢!
英文:
Here's my problem. I'm using gqlgen library to run a GraphQL server. In my database I have a MongoDB document that looks like this:
{
"_id": ObjectID(...),
"somefield": "data",
"anArrayOfObjects": [
{
"field1": "value1",
"field2": "value2
},
...
]
}
What I want is to be able to only decode the field anArrayOfObjects
into a slice (may look like []MyObj
, where MyObj
is a struct).
(For a little context, I only want this field because the array is quite large and it has it's own GraphQL resolver).
Here's currently what I have tried:
ObjectID, err := primitive.ObjectIDFromHex("someid")
// do some error check
opts := options.FindOne().SetProjection(
bson.D{{Key: "anArrayOfObjects", Value: 1}, {Key: "_id", Value: 0}},
)
myslice = []MyObj{}
err := coll.FindOne(ctx, bson.M{"_id": ObjectID}, opts).Decode(&myslice)
// err is "cannot decode document into []MyObj"
If instead I run
result = primitive.D{} // or primitive.M{}
err := coll.FindOne(ctx, bson.M{"_id": ObjectID}, opts).Decode(&result)
// err is nil and result contains everything I want but not in the "ideal" data structure
Doing the latter, I reckon I can iterate through result
and then map everything to every struct field (similar to this answer). But my intuition is that probably there is a better way to do this than that.
Thanks in advance!
答案1
得分: 0
您的查询结果将是一个包含anArrayOfObjects
字段下数组的文档,而不仅仅是该字段的数组值。而且您不能将文档解码为Go切片,这就是错误消息告诉您的内容。
因此,您需要将其解组为具有该字段的结构体:
var result struct{
MySlice []MyObj `bson:"anArrayOfObjects"`
}
err := coll.FindOne(ctx, bson.M{"_id": ObjectID}, opts).Decode(&result)
来自MongoDB的数组将是result.MySlice
。
英文:
The result of your query will be a document holding the array under the anArrayOfObjects
field, and not the array value of that field alone. And you can't decode a document into a Go slice, that's what the error message tells you.
So unmarshal into a struct having that field:
var result struct{
MySlice []MyObj `bson:"anArrayOfObjects"`
}
err := coll.FindOne(ctx, bson.M{"_id": ObjectID}, opts).Decode(&result)
The array from MongoDB will be result.MySlice
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论