2

I am faced with a problem where I am not sure which path to take. So I am asking it here. I have an application where there can be products and there can be metadata for a product. These metadata can be created and deleted from the front end. So let's say, today a each product has two meta data (e.g. Name, Price) then tomorrow it can be three, four or more or even less than two. So this is dynamic. I am trying to represent the data as follows

Product = 
{
    "_id": mongo
    "Name": string
    "Description": string
    "BasePrice": number
    "CreatedBy": user mongo _id
    "CreatedAt": timestamp
    "ModifiedAt": timestamp
    "MetaData": BSON object (having all the keys from ProductMetadata collection and their values. e.g. {"Category": "table ware", "Material": "oak wood, copper", "Length": 5.6})

}

ProductMetadata = 
{
    "_id": mongo
    "Name": string (e.g. - "Category" or "Material" or "Height")
    "Type": string (indicating what kind of value it can hold like string/integer/array. e.g. - "string")
    "CreatedAt": timestamp
    "ModifiedAt": timestamp
}

As you can see this is a pure dynamic situation so having a structure at the code level which represent the model is impossible.

My problem is, how do I implement such a thing using mgo and Go lang? If I need to use reflection then can some one please point me towards a good blog/tutorial where I can get a little bit more info. Or if you think that there is a fundamental problem in the approach of modeling the data then please correct me so that it can be easily implemented using Go.

In Python, it would not be a problem to implement this. I know that. But I am confused about the Go implementation.

Please help.

Thanks in advance

SRC
  • 2,123
  • 3
  • 31
  • 44

1 Answers1

3

If Keys for metadata are unique, why not just use a map.

meaning your Product struct looks like:

struct Product {
    ID        bson.ObjectId `bson:"_id,omitempty"`
    Name string
    Description string
     ... omitted other fields ...
    MetaData map[string]map[string]interface{} // map of string -> map of string -> anything
}

If you can have more than one instance of a given meta data, ie: 2 categories, use a list:

struct Product {
    ID        bson.ObjectId `bson:"_id,omitempty"`
    Name string
    Description string
     ... omitted other fields ...
    MetaData []map[string]interface{} // list of maps of string -> anything
}
David Budworth
  • 11,248
  • 1
  • 36
  • 45
  • This is also a good solution David. I will try this out. Thanks – SRC Jan 26 '16 at 04:33
  • You might want to use https://godoc.org/gopkg.in/mgo.v2/bson#M instead of map[string]interface{} – Ezequiel Moreno Jan 26 '16 at 04:48
  • Sort of agree on the bson.M. Only reason I'm weary of it is that it leaks the bson package in to the rest of your code wherever you want to create a new literal version of that map. I generally try to minimize third party imports where possible so I have less to maintain later when I inevitably change my mine on what library to use for a given purpose. – David Budworth Jan 26 '16 at 07:01
  • valid argument. I agree – SRC Jan 26 '16 at 07:37