0

I'm trying to insert to MongoDB with Go where one field will have dynamic data. In my case, it will come from the other service through gRPC but I simplified example to this:

package main

import (
    "context"
    "fmt"
    _struct "github.com/golang/protobuf/ptypes/struct"
    "go.mongodb.org/mongo-driver/bson/primitive"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "log"
)

type siteItem struct {
    ID   primitive.ObjectID `bson:"_id,omitempty"`
    Name string             `bson:"name"`

    // Data string     `bson:"data"`
    Data *_struct.Value `bson:"data"`
}

func main() {
    client, _ := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017"))
    client.Connect(context.TODO())
    collection := client.Database("site").Collection("sites")

    data := siteItem{
        Name: "Test name",

        // Data: "Test data",
        Data: &_struct.Value{
            Kind: &_struct.Value_StringValue{
                StringValue: "String from struct",
            },
        },
    }

    res, err := collection.InsertOne(context.Background(), data)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(res)
}

And I get an error: cannot transform type main.siteItem to a BSON Document: no encoder found for structpb.isValue_Kind

If I use string instead of *_struct.Value - it works just fine. But in my case Data: might have any value that comes from JSON.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Arūnas Smaliukas
  • 3,231
  • 6
  • 27
  • 46

1 Answers1

0

One way you can deal with this is by tagging the struct with bson tags, which is not always possible. I've dealt with this case using one of the following, depending on the situation:

  • Use map[string]interface{} and JSON marshaling:
type Item struct {
   Data map[string]interface{} `bson:"data"`
}

...
// Writing to db
data,_:=json.Marshal(someStruct)
json.Unmarshal(data,&item.Data)
// Reading from db
data,_:=json.Marshal(item.Data)
json.Unmarshal(data,&result.Data)
  • Store the raw JSON data by declaring Data as string instead of map[string]interface{}
Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • `{ "_id" : ObjectId("5e5ea8d418e0c475983b45ea"), "name" : "Test name", "data" : { "Kind" : { "StringValue" : "String from struct" } } }` - thanks, I do not get error now, but in database I see all the weird structure... with `Kind` and `StringValue` keys.. I need to learn golang more.. – Arūnas Smaliukas Mar 03 '20 at 19:10
  • You can add json tags to your structs to control how those keys are named. – Burak Serdar Mar 03 '20 at 19:15
  • Ok, I mark this question as answered, as I succeeded to insert JSON without an error, but I created one more question, with more details: https://stackoverflow.com/questions/60523142/go-converting-ptypes-struct-value-to-bson – Arūnas Smaliukas Mar 04 '20 at 09:47