使用_t定义查询C#驱动程序插入的记录

I want to query data which was inserted by C# mongodriver with polymorhism. The query will be done by Golang driver. Structure of the data is shown below. I want to map _t to structs, in other words, I want to apply polymorhism to record in Go. Is it possible to do it in Golang mongo drivers? The list of structs is below as well.

One record example from mongo collection

{"_id" : "asdasda12312312asdasda",
"structure" : [ 
                    {
                        "_t" : "AObject",
                        "Text" : "asdasdasda",
                        "State" : "asdasda"
                    }, 
                    {
                        "_t" : "BObject",
                        "Number" : "123",
                    }, 
                    {
                        "_t" : "CObject",
                        "Testing" : "Pompeo"
                    }
                ]
}

Go Structs

type Data struct{
  _id string
  Structure []Object
}

type Object interface{
}

type AObject struct {
  Text  string
  State string 
}
type BObject struct {
  Number  string 
}
type CObject struct {
  Testing  string
}

Thanks

What mongo driver are you using? "_t" is a parameter used to determine what type was serialized if the current type is different than the nominal type. It's also used for normal JSON serialization so you have one of three ways I can think of.

  1. Using different GO mongo driver which supports it. I would suggest using https://github.com/mongodb/mongo-go-driver which is official MongoDB Go Driver
  2. Write switch / case statement to deserialize it yourself
type MongoObject struct {
        // Contains all fields from all objects
        _t string
        Text string
        State string
        Number string
        Testing string
}

func DeserializeObject(object MongoObject) Object{
        switch t {
        case "AObject":
        return &AObject{Text: object.Text, State: object.State}
        case "BObject":
        return &BObject{Number: object.Text}
        case "CObject":
        return &CObject{Testing: object.Testing}
    }
}
  1. You can get data from mongo as JSON and use certain marshaling to do it for you

Using interfaces generally is problematic, because the libraries doing the unmarshaling would have hard time deciding what type to choose. You could use custom unmarshaler in which you choose the appropriate type, but that's more cumbersome and complex.

Easiest is to use concrete struct types. You have to use struct tags to map between struct fields and fields in the MongoDB documents. One important thing is that in Go fields must be exported else they cannot be populated / read by libraries that do the work. For it to be exported, their name must start with a capital letter, and underscore (_) isn't one of them.

If the (sub)documents may have different fields based on a value, you may add all, and the ones that are present will be properly unmarshaled.

Your document may be modeled like this:

type Data struct {
    ID        string   `bson:"_id"`
    Structure []Object `bson:"structure"`
}

type Object struct {
    T       string `bson:"_t"`
    Text    string `bson:"Text,omitempty"`
    State   string `bson:"State,omitempty"`
    Number  string `bson:"Number,omitempty"`
    Testing string `bson:"Testing,omitempty"`
}

Note that the ,omitempty option isn't required for unmarshaling, but if you'd want to use these same types for marsaling (e.g. saving a new document), the ,omitempty option will ensure to leave out fields that are empty.

Also note that if this doesn't satisfy you, there's nothing stopping you to post-process the result. You can switch on the available Object.T field and create "dynamic" instances of types of your choosing.