How to save struct based type with a map property into mongodb - go

I want to use mongodb as session storage and save a struct based data type into mongodb.
The struct type looks like:
type Session struct {
Id string
Data map[string]interface{}
}
And create reference to Session struct type and put some data into properties like:
type Authen struct {
Name, Email string
}
a := &Authen{Name: "Foo", Email: "foo#example.com"}
s := &Session{}
s.Id = "555555"
s.Data["logged"] = a
How to save the session data s into mongodb and how to query those data back and save into a reference again?
I think the problem can occurs with the data property of type map[string]interface{}.
As driver to mongodb I would use mgo

There's nothing special to be done for inserts. Just insert that session value into the database as usual, and the map type will be properly inserted:
err := collection.Insert(&session)
Assuming the structure described, this will insert the following document into the database:
{id: "555555", data: {logged: {name: "foo", email: "foo#example.com"}}}
You cannot easily query it back like that, though, because the map[string]interface{} does not give the bson package a good hint about what the value type is (it'll end up as a map, instead of Authen). To workaround this, you'd need to implement the bson.Setter interface in the type used by the Data field.

Related

insert rows with sqlx, is it possible to avoid listing the fields explicitly?

I'm using sqlx library like the following:
type MyData {
Field1 string `json:"db:field1"`
Field2 string `json:"db:field2"`
}
...
res, err := db.Exec("INSERT INTO XXX (field1, field2) VALUES (?, ?)", data.XX, data.XX)
Is it possible to avoid specifying "field1, field2" explicitly, and let sqlx create the query and binding automatically, e.g
db.Exec2("table_name", data)
I didn't find a relevant method to do that.
No. The package sqlx is just a wrapper around the DB driver. It is not an ORM. It expects user-supplied, valid SQL query strings. You may construct the query strings programmatically, and design some method that builds the column names from struct tags using reflect package, but why reinventing the wheel? The advantage of using a lower-level package as sqlx is exactly to maintain your own queries in exchange for not introducing an ORM framework in your codebase. With an ORM instead it is the other way around.
Gorm instead has a set of conventions that do what you want out of the box. You wouldn't even have to specify the db tags:
GORM prefer convention over configuration, by default, GORM uses ID as primary key, pluralize struct name to snake_cases as table name, snake_case as column name, and uses CreatedAt, UpdatedAt to track creating/updating time
type MyData {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
}
data := MyData {
Field1: "foo",
Field2: "bar",
}
result := db.Create(&data)
// results in something like this:
// INSERT INTO my_datas (field1, field2) VALUES ('foo', 'bar')

How to query in GraphQL with no fixed input object contents?

I want to query to get a string, for which I have to provide a input object, however the input data can have multiple optional keys and quite grow large as well. So I just wanted something like Object as data type while defining schema.
// example of supposed schema
input SampleInput {
id: ID
data: Object // such thing not exist, wanted something like this.
}
type Query {
myquery(input: SampleInput!): String
}
here data input can be quite large so I do not want to define a type for it. is there a way around this?

Serialize to JSON dynamic structure

All examples of working with JSON describe how to serialize to JSON simple or user types (like a struct).
But I have a different case: a) I don't know the fields of my type/object b) every object will have different types.
Here is my case in pseudocode:
while `select * from item` do
while `select fieldname, fieldvalue from fields where fields.itemid = item.id` do
...
For each entity in my database I get field names and field values. In the result I need to get something like this:
{
"item.field1": value,
...
"item.fieldN": value,
"custom_fields": {
"fields.field1": value,
...
"fields.fieldK": value
}
}
What is the best way to do it in Go? Is there any useful libraries or functions in standard library ?
Update: The source of data is the database. In the result i need to get JSON as string to POST it to external web service. So, the program just read data from database and make POST requests to REST service.
What exactly is your target type supposed to be? It can't be a struct since you do not know the fields beforehand.
The only fitting type to me seems to be a map of type map[string]interface{}: with it any nested structure can be achieved:
a := map[string]interface{}{
"item.field1": "val1",
"item.field2": "val2",
"item.fieldN": "valN",
"custom_fields": map[string]interface{}{
"fields.field1": "cval1",
"fields.field2": "cval2",
},
}
b, err := json.Marshal(a)
See playground sample here.
Filling this structure from a database as you hinted at should probably be a custom script (not using json).
Note: custom_fields can also be of other types depending on what type the value column is in the database. If the value column is a string use map[string]string.

Gocql custom marshaller

I have a table with a tuple column that is made up of an int64 paired with a uuid:
CREATE TABLE ks.mytable {
fileid frozen <tuple <bigint, uuid>>,
hits counter,
...
and I can currently set the field using a cql statement like:
UPDATE ks.mytable hits = hits + 1 WHERE fileid=(? ?);
and I pass in 2 variables as arguments, an int64 and a gocql.UUID.
Instead of moving 2 variables around everywhere, I want to put these in a struct, something like
type MyID struct {
id int64
uid gocql.UUID
}
then use a Marshaller to pass these into the UPDATE statement.
Is this possible? I am not sure if I can pass in a single variable for the tuple field. If so, how can I do this? I can't figure out how - I was trying to mimic https://github.com/gocql/gocql/blob/master/marshal_test.go#L935 but I'm getting errors where I can't set the fields in the struct (cannot refer to unexported field or method proto)
As you mentioned, you are getting the following error:
cannot refer to unexported field or method proto
This means you need to export your fields inside the struct and that means beginning with a capital letter in Go. So your struct should be:
type MyID struct {
Id int64
Uid gocql.UUID
}
Then, it should work.

Getting ID from Google's datastore using Golang

I have a Go struct:
type Foo struct{
Name: string
Age: int
}
I am able to save and retrieve Foos in datastore.
So I may edit a Foo, I want to get the ID that datastore assigns a Foo, to use in an anchor.
I verified that IDs are assigned using Google's datastore dashboard, but how do I get the ID off of a retrieved Foo?
GetAll returns the keys along with any error.
keys, err := q.GetAll(c, &foos)
keys is an array of datastore.Key

Resources