Retrieving arbitrary data into nested object with ORM - postgresql

I am attempting to develop an api in go, to allow the user to specify an arbitrary data structure, and easily set up endpoints that perform CRUD operations on an auto generated postgres database, based on the structure that they define.
For now, I have been using gorm, and am able to have a database automatically generated based on a user-defined set of structs, that support all types of relations (has one, one to many, etc.). I am also able to insert into the generated database, when JSON is sent in through the endpoints.
The issue I have discovered, is when I try to receive the data. It seems where many of the go ORMs fall short on, is mapping data from all tables back into the nested structs of the parent struct.
For example, if the user defines:
type Member struct {
ID string
FirstName string
Hometown Hometown `gorm:"ForeignKey:MemberRefer"`
}
type Hometown struct {
ID string
City string
Province string
MemberRefer string
}
The database creates the tables:
Members
id
first_name
Hometowns
id
city
province
member_refer
However, when retrieving the data, all that is mapped back is:
{
"id": "dc2bb591-506f-40a5-a141-bdc0c8410ba1",
"name": "Kevin Krishna",
"hometown": {
"id": "",
"city": "",
"province": ""
}
}
Does anyone know of a go orm that supports this kind of behaviour?
Thanks

5 sec google search showed me the answer:
Preloading associations
Now that you actually have them properly related, you can .Preload() get the nested object you want:
db.Preload("GoogleAccount").First(&user)
Get nested object in structure in gorm
https://www.google.com/search?q=gorm+nested+struct+golang

Related

Is there a way to create public/private fields for a mongodb schema in golang?

I'm creating a backend for a moderately large-scale application, and I came across a difficulty with restraining what fields users can access. For instance, a user should not be able to modify their follower count with a PUT request to an update endpoint, yet the only way to really remove the followerCount field from the golang struct representing the user schema is by creating an entirely new schema for updates in particular. I've been doing this, and my backend code base is way more complex than it needs to be, to the point where it's nearly unmanageable.
Here's an example of the schemas I have:
type User struct {
ID primitive.ObjectID `bson:"_id" json:"_id"`
// CHANGEABLE
Username string `bson:"username" json:"username"`
Email string `bson:"email" json:"email"`
Password string `bson:"password" json:"password"`
Archived bool `bson:"archived" json:"archived"`
// UNCHANGEABLE
Sessions []primitive.ObjectID `bson:"sessions" json:"sessions"`
IsCreator bool `bson:"isCreator" json:"isCreator"`
FollowerCount int `bson:"followerCount" json:"followerCount"`
}
and for updates specifically
type UserUpdate struct {
Username string `bson:"username,omitempty" json:"username,omitempty"`
Email string `bson:"email,omitempty" json:"email,omitempty"`
Password string `bson:"password,omitempty" json:"password,omitempty"`
Archived bool `bson:"archived,omitempty" json:"archived,omitempty"`
}
Is there a way to make public/private fields within a mongo schema so I can simplify this process? And if not, can you advise me on a better solution? Nothing is coming to mind for me.
I've continued creating new "sub-schemas" built off the same schema for specific purposes (i.e. Creation, Updating, Getting, etc.). Changing one field name takes nearly 30 minutes to change across schemas, which is not ideal.

invalid sql type (slice) for postgres

I want to AutoMigrate my Model but I get this error when running up:
invalid sql type (slice) for postgres
Here is my struct:
type Tracking struct {
ServerID int64
Tracks []map[string]interface{}
}
Im using gorm to work with the DB. (github.com/jinzhu/gorm)
The error comes from: AutoMigrate(&Tracking{})
Is there a solution to this?
Thanks already
The short answer is gorm and most SQL databases don't support slices as a data type. To work around this you need to tell gorm to set up a many to many relationship table.
Table1 <----> (Table1/Table2) <----> Table2
I was attempting the same thing, the gorm documentation advised the following and it worked for me:
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
}
Taking a guess at yours I would do:
type Tracking struct {
ServerID int64
Tracks []Tracks `gorm:"many2many:tracking_tracks;"`
}
type Tracks struct {
gorm.Model
Text string
}
This sets up three tables as previously mentioned, your trackings table, your tracks table and a third one called tracking_tracks which will store the id to id relationship (many to many)
It's then important to note that for data you are querying from one table where there is a relationship with another table, you will need to Preload() those tables.
Using the gorm example you would do the following
var users []User
db.Preload("Languages").Find(&users)
Not doing this will return the users with the languages column empty.
If many to many doesn't suit you can try a has many or one to many relationship if that is more suitable https://gorm.io/docs/has_many.html

Selected Updates in Nested AppSync Schema

I am trying to carry out selected upates of individual nested fields with a DynamoDB table which is connected to an AppSync interface. I am able to update individual top level fields but when it comes to nested fields I am unsure how to approach. I am a newbie to this so perhaps I am thinking about this wrong and I need to flatten the data through the schema so that the data is flat in the DynamoDb tables. I have struggled to find an example of how to tackle this kind of situation with fairly complex tables. I am using the Custom Types to bring some standardisation across the App and different resolvers/.
We have a AppSync Schema defined approximately like this
type Main_entries {
id: String!
title: String!
recordInfo: CustomType
}
Type CustomType {
fieldA: String
fieldB: String
fieldC: String
}
What I have are some main types but also some Custom Types used throughout the application. What I want to be able to do is to update fieldB whilst keeping the rest of the data intact.
I have used the UpdateItem approach here
With this I can say update title whilst keeping the rest of the record intact but if my Mutation instructs fieldB to be updated a SET is created to update the entire recordInfo type so fieldA and fieldC are omitted.
Does anyone know of any ideas or even better know where there may be some examples.
Many thanks in advance.

RESTFul way to reference resource with unique fields

One of the requirements for our REST interface is that each resource be identifiable by unique fields (aside from the primary identifier). The reason for this is that we want to be able to handle bulk importing data - in which case the client can't know the system generated primary identifiers.
This means we have to be able to reference our resources by unique fields. Using a primary key our read requests look like this:
GET example.com/rest/customers/1
and to get orders related to that customer
GET example.com/rest/customers/1/orders
Now, lets assume two fields in customer identify it uniquely, name ("foo") and businessId ("bar"). Given that, I came up with the following URI to get the orders for this customer:
GET example.com/someotherpath/customers/foo,bar/orders
But I don't like that I have a different path to identify that this is a resource being accessed via unique fields. How would you structure the above query in a RESTful way using unique fields instead of the primary key?
Further, an order looks like this:
{
<SNIP>
"orderId" : "42"
"_links": {
"customer": {
"href" : "rest/customers/1"
"key": [ "foo", "bar" ]
}
},
}
Any issues with allowing client to interchangeably specify href OR key when communicating with the interface?
For the first bit, I just wouldn't do it. If a customer has a unique id (and they should), I wouldn't allow end users to specify N other fields that happen to also uniquely identify the customer. It's messy for the user (which field goes first?) and also messy for you on the back end.
For the second bit, the issue is: what happens when they specify both? Which takes precedence? Are they going to remember? Do you want to have to support both? It's generally a good idea to only allow one way to do any particular thing if you can get away with it.

Odata to insert data into relational table

I have created OData service for a relational table. I am trying to figure out how my post query will look like when posting to tables that has foreign key relation and also to reduce number of calls.
Example tables are:
Person
PersonID
Name
EmailAddress
Residence
ResidenceID
PersonID
Address
In order to create new entry into residence table, typically I will find out the PersonID based on the name or email address and then insert into Residence table.
How can I accomplish the same using my OData JSON api with single call? Is it possible? I am using fiddler to test the service.
Thanks in advance.
-ap
In general, there's not a really good way to do this in OData - but don't stop reading, I'll explain why and provide a few suggestions.
The reason you should think twice about doing this in production is because of the fragility of the insert process. What happens if you have two people in the database with the same name? What if there's nobody with that name? What if you misspelled the name? Would you throw an HTTP error for duplicates? Would they have to retry the insert? <- In essence, there are a ton of questions that arise because the user didn't actually pick a particular record for binding to the new record. This process is greatly simplified if you select the Person up front and just insert the new Residence with a binding to the PersonID. In the new JSON format for OData, that would look something like this:
{
"odata.type": "My.User",
"ReferredBy#odata.bind": "http://.../MyService.svc/Users('haoche')",
"BillingAddress": {
"odata.type": "My.Address",
"City": "Clinton",
"Line1": "23456 Cleveland St",
"Line2": null,
"State": "TX",
"ZipCode": "98052"
},
"DisplayName": "David Hamilton",
"FavoriteTags": [],
"JoinedAt": "2012-10-05T14:14:43.1229977-07:00",
"LastSeenAt": "2012-10-05T14:14:43.1269991-07:00",
"UserID": "davham"
}
That "ReferredBy#odata.bind" is where you put the ID of the person you're linking to. If you're not using the new OData format, the payload would look like this (see example 2). Shameless plug: this is why you should be using the new JSON format :).
So the primary suggestion I have is that I would really, strongly recommend that you have users look up the data first rather than trying to combine two operations into one. If, however, you're really set on having one operation, you could do so with a service operation or an action, depending on what version of OData you're using.