Go type assertion for MongoDB []bson.M{}/primitive.A type

130 views
Skip to first unread message

Tong Sun

unread,
Nov 16, 2023, 12:10:49 PM11/16/23
to golang-nuts
Further on with the question 
https://stackoverflow.com/questions/60072372/filtering-values-out-of-a-bson-m-in-golang/
where the answer says to use `range server.installed` while the comment says

server.host undefined (type string has no field or method subject)

This is what I've tried with the MongoDB `[]bson.M{}` type results (obtained from like `$lookup`):

The []bson.M{} type of result I'm getting is:

[map[_id:ObjectID("65529d178688bac31b739f82") author:[map[_id:ObjectID("65529d168688bac31b739f81") created_at:1699912982379 name:Mehran updated_at:1699912982379]] author_id:ObjectID("65529d168688bac31b739f81") created_at:1699912983386 name:Test pages:124 updated_at:1699912983386]]

I've made several attempts but was unable to access the author field of the lookup result in Go.

a := []author{} 
for _, val := range result { a = append(a, val["author"].(primitive.A)[0]) }

  • If using val.author, I'm getting val.author undefined (type primitive.M has no field or method author)
  • If using val["author"], I'm getting invalid operation: cannot index val["author"] (map index expression of type interface{})
  • If using val["author"].(primitive.A)[0], I'm getting cannot use val["author"].(primitive.A)[0] (variable of type interface{}) as author value in argument to append: need type assertion

And how to go about to fix this "need type assertion" just stumbled me, as I've tried val["author"].(primitive.A).([]main.author)[0], or []author(val["author"].(primitive.A))[0], but I'm getting invalid operation: cannot call non-function val["author"].(primitive.A) (comma, ok expression of type primitive.A)

and I've now run out of ideas how to fix it. 
Please help


burak serdar

unread,
Nov 16, 2023, 12:20:13 PM11/16/23
to Tong Sun, golang-nuts
val["author"].(primitive.A)[0] is correct, but the type of that
expression is not author, it is bson.M. You might consider using a
tagged struct to unmarshal this.
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/4c9bfd40-4de6-4423-9c0e-31b79b144bd5n%40googlegroups.com.

Tong Sun

unread,
Nov 16, 2023, 12:38:57 PM11/16/23
to golang-nuts
Thanks for the hint. would you elaborate a bit more please as I'm still unsure how to do it. and the closes hits that I found are


But neither covers how to unmarshal bson.M types. I got either:

cannot use r (variable of type interface{}) as []byte value in argument to bson.Unmarshal: need type assertion

Or with:

r := val["author"].(primitive.A)[0]
var a1 author
bson.Unmarshal(r.([]byte), &a1)
a = append(a, a1)

I'm getting:

panic: interface conversion: interface {} is primitive.M, not []uint8


On Thursday, November 16, 2023 at 12:20:13 PM UTC-5 burak serdar wrote:
val["author"].(primitive.A)[0] is correct, but the type of that
expression is not author, it is bson.M. You might consider using a
tagged struct to unmarshal this.

burak serdar

unread,
Nov 16, 2023, 12:53:45 PM11/16/23
to Tong Sun, golang-nuts
Something like this:

type Author struct {
ID primitive.ObjectID `bson:"_id"`
CreatedAt time.Time `bson:"created_at"`
...
}

type Data struct {
Author []Author `bson:"author"`
}


Then you read the results into var result []Data
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/d3d75521-c618-45f1-a734-59730cf01364n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages