Last active
June 18, 2025 19:05
-
-
Save ctalladen78/43b946f27d7dd867aacb7d386da7c191 to your computer and use it in GitHub Desktop.
Basic CRUD operations with single table dynamodb design
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| // "errors" | |
| "fmt" | |
| "log" | |
| "time" | |
| // "sync" | |
| "github.com/aws/aws-sdk-go/aws" | |
| "github.com/aws/aws-sdk-go/aws/session" | |
| "github.com/aws/aws-sdk-go/service/dynamodb" | |
| "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" | |
| ) | |
| // TODO | |
| type DbController struct { | |
| conn *dynamodb.DynamoDB | |
| } | |
| // https://docs.aws.amazon.com/sdk-for-go/api/aws/endpoints/ | |
| // https://docs.aws.amazon.com/sdk-for-go/api/aws/session/ | |
| // TODO start remote aws dynamodb session | |
| // TODO start remote aws api gateway session | |
| // uses localhost only | |
| func InitDbConnection(h string) *DbController { | |
| return &DbController{ | |
| conn: dynamodb.New(session.New(&aws.Config{ | |
| Region: aws.String("us-east-1"), | |
| Endpoint: aws.String(h), | |
| })), | |
| } | |
| } | |
| func (ctrl *DbController) GetUser(userId string) (interface{}, error) { | |
| fmt.Println("GET USER", userId) | |
| var pkey = map[string]*dynamodb.AttributeValue{ | |
| "object_id": { | |
| S: aws.String("USER"), | |
| }, | |
| "object_sk": { | |
| S: aws.String(userId), | |
| }, | |
| } | |
| // TodoObject and table key attributes do not match because of extra "cratedat" field | |
| // pkey, err := dynamodbattribute.MarshalMap(t) | |
| input := &dynamodb.GetItemInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| Key: pkey, | |
| } | |
| res, err := ctrl.conn.GetItem(input) | |
| // user := &User{} | |
| if err != nil { | |
| return nil, err | |
| } | |
| var out interface{} | |
| err = dynamodbattribute.UnmarshalMap(res.Item, &out) | |
| if err != nil { | |
| return nil, err | |
| } | |
| log.Println("GET ITEM output", res) | |
| return out, nil | |
| } | |
| func (ctrl *DbController) SaveUserToDBGoroutine(uid string, email string, name string, avatar string, fchan chan *User) { | |
| u := &User{} | |
| u.ObjectId = string([]byte("USER")) | |
| u.ObjectSk = string([]byte("USER-" + uid)) | |
| u.AvatarLink = avatar | |
| u.Email = email | |
| u.Name = name | |
| u.Bio = "Hi!" | |
| u.CreatedAt = time.Now().Format(time.RFC3339) | |
| user, err := ctrl.SaveItemST(u) | |
| if err != nil { | |
| log.Println("ERROR ", err) | |
| } | |
| fmt.Printf("SAVE USER SUCCESS %s", user) | |
| fchan <- u | |
| } | |
| func getTripItemInListGoRoutine(pkid string, skid string, imap map[string]*Trip, retval chan map[string]*Trip) { | |
| trip, err := ctrl.GetTripItemST(pkid, skid) | |
| if err != nil { | |
| retval <- nil | |
| } | |
| id := fmt.Sprintf("%s+%s", pkid, skid) | |
| imap[id] = trip.(*Trip) | |
| retval <- imap | |
| } | |
| func getItemInListGoRoutine(pkid string, skid string, imap map[string]interface{}, retval chan map[string]interface{}) { | |
| res, err := ctrl.GetItemDetailST(pkid, skid) | |
| if err != nil { | |
| imap[pkid] = nil | |
| } | |
| id := fmt.Sprintf("%s+%s", pkid, skid) | |
| imap[id] = res | |
| retval <- imap | |
| } | |
| func (ctrl *DbController) SaveItemST(item interface{}) (interface{}, error) { | |
| newItemAV, err := dynamodbattribute.MarshalMap(item) // conver interface object to av item map | |
| // log.Printf("PUT INPUT AV %v", newItemAV) | |
| if err != nil { | |
| return nil, err | |
| } | |
| input := &dynamodb.PutItemInput{ | |
| Item: newItemAV, | |
| // ConditionExpression: aws.String("attribute_exists(object_id)"), | |
| TableName: aws.String("tasl_app_main"), | |
| // ConditionExpression: aws.String("if not exists") | |
| } | |
| log.Printf("ADD ITEM %v", input) | |
| o, err := ctrl.conn.PutItem(input) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return o.Attributes, err | |
| } | |
| func (ctrl *DbController) GetTripItemST(pkid string, skid string) (interface{}, error) { | |
| // pkid := fmt.Sprintf("%s-%s", item_pref, objId) | |
| // skid := fmt.Sprintf("DETAIL-%s", objId) | |
| var pkey = map[string]*dynamodb.AttributeValue{ | |
| "object_id": { | |
| S: aws.String(pkid), | |
| }, | |
| "object_sk": { | |
| S: aws.String(skid), | |
| }, | |
| } | |
| // TodoObject and table key attributes do not match because of extra "cratedat" field | |
| // pkey, err := dynamodbattribute.MarshalMap(t) | |
| input := &dynamodb.GetItemInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| Key: pkey, | |
| } | |
| log.Println("GET ITEM input", input) | |
| res, err := ctrl.conn.GetItem(input) | |
| if err != nil { | |
| return nil, err | |
| } | |
| var out *Trip | |
| err = dynamodbattribute.UnmarshalMap(res.Item, &out) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return out, nil | |
| } | |
| func (ctrl *DbController) GetItemDetailST(pkid string, skid string) (interface{}, error) { | |
| // pkid := fmt.Sprintf("%s-%s", item_pref, objId) | |
| // skid := fmt.Sprintf("DETAIL-%s", objId) | |
| var pkey = map[string]*dynamodb.AttributeValue{ | |
| "object_id": { | |
| S: aws.String(pkid), | |
| }, | |
| "object_sk": { | |
| S: aws.String(skid), | |
| }, | |
| } | |
| // TodoObject and table key attributes do not match because of extra "cratedat" field | |
| // pkey, err := dynamodbattribute.MarshalMap(t) | |
| input := &dynamodb.GetItemInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| Key: pkey, | |
| } | |
| log.Println("GET ITEM input", input) | |
| res, err := ctrl.conn.GetItem(input) | |
| if err != nil { | |
| return nil, err | |
| } | |
| var out interface{} | |
| err = dynamodbattribute.UnmarshalMap(res.Item, &out) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return out, nil | |
| } | |
| func (ctrl *DbController) QueryCityST(cityId string) (interface{}, error) { | |
| pkid := fmt.Sprintf("CITY") | |
| c, err := ctrl.GetItemDetailST(pkid, cityId) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return c, nil | |
| } | |
| func (ctrl *DbController) GetUserProfileDetailsST(userId string) (interface{}, error) { | |
| pkid := fmt.Sprintf("USER") | |
| u, err := ctrl.GetItemDetailST(pkid, userId) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return u, nil | |
| } | |
| func queryPlaceCountGoRoutine(tripID string, cmap map[string]int, retval chan map[string]int) { | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":tid": {S: aws.String(tripID)}, | |
| ":pfx": {S: aws.String("TRIP-LOCATION-")}, | |
| }, | |
| // IndexName: aws.String("user_idx"), | |
| KeyConditionExpression: aws.String("object_id = :tid and begins_with(object_sk, :pfx)"), | |
| ProjectionExpression: aws.String("place_id"), | |
| Limit: aws.Int64(50), | |
| } | |
| fmt.Println("QUERY PLACE LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var plist []interface{} | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &plist) | |
| if err != nil { | |
| cmap[tripID] = 0 | |
| retval <- cmap | |
| } | |
| cmap[tripID] = len(plist) | |
| retval <- cmap | |
| } | |
| func (ctrl *DbController) QueryAllCitiesST() ([]interface{}, error) { | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":ct": {S: aws.String("CITY")}, | |
| ":skpref": {S: aws.String("CITY")}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :ct and begins_with(object_sk, :skpref) "), | |
| } | |
| fmt.Println("QUERY CITY LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var clist []interface{} | |
| // fmt.Println(res) | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &clist) | |
| if err != nil { | |
| return nil, err | |
| } | |
| // TODO sort by city ranking | |
| nlist, err := sortCityList(&clist) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return nlist, nil | |
| } | |
| func (ctrl *DbController) getPlaceCount(tripId string) (int, error) { | |
| // TODO query place count only | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":tid": {S: aws.String(tripId)}, | |
| ":skpref": {S: aws.String("PLACE-LOCATION")}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :tid and begins_with(object_sk, :skpref) "), | |
| } | |
| // fmt.Println("QUERY CITY LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var slist int | |
| fmt.Println("GET PLACE COUNT ", res) | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &slist) | |
| if err != nil { | |
| return 0, err | |
| } | |
| // suggestions count only | |
| qInput = &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":tid": {S: aws.String(tripId)}, | |
| ":skpref": {S: aws.String("SUGGESTION-LOCATION")}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :tid and begins_with(object_sk, :skpref) "), | |
| } | |
| // fmt.Println("QUERY CITY LIST INPUT", qInput) | |
| res, err = ctrl.conn.Query(qInput) | |
| var plist int | |
| fmt.Println("GET PLACE COUNT ", res) | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &plist) | |
| if err != nil { | |
| return 0, err | |
| } | |
| return 0, err | |
| } | |
| func sortCityList(clist *[]interface{}) ([]interface{}, error) { | |
| var newList []interface{} | |
| // rank := []string{"New York City", "Los Angeles", "San Fransisco", "Tokyo", "Paris", | |
| // "Seoul", "Kyoto", "London", "Berlin", "Rome", "Venezia", "Vienna", "Stockholm", "Barcelona", "Prague", "Sydney", "Bangkok", "Taipei", "Singapore", | |
| // "Miami", "Mexico City", "Las Vegas"} | |
| rank := []string{"New York City", "Los Angeles", "San Fransisco", "Tokyo", "Paris", | |
| "Seoul", "Kyoto", "London", "Berlin", "Rome", "Venezia", "Vienna", "Stockholm", "Barcelona", "Sydney", "Bangkok", "Taipei", "Singapore", | |
| "Miami", "Las Vegas"} | |
| for i := range rank { | |
| for _, cmap := range *clist { | |
| // https://stackoverflow.com/questions/31815969/go-cannot-range-over-my-var-type-interface | |
| if city, ok := cmap.(map[string]interface{}); ok { | |
| // log.Printf(" PRINT CITY LIST CITY %s ", city["city_name"]) | |
| // for key, val := range city { | |
| // log.Printf(" PRINT CITY LIST CITY %s : %s", key, val) | |
| // } | |
| if rank[i] == city["city_name"] { | |
| newList = append(newList, city) | |
| } | |
| } | |
| } | |
| } | |
| // log.Printf(" NEW CITY LIST %s ", newList) | |
| return newList, nil | |
| } | |
| func (ctrl *DbController) GetBucketList(userid string) (interface{}, error) { | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":uid": {S: aws.String(userid)}, | |
| ":pfx": {S: aws.String("BUCKET-ITEM-")}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :uid and begins_with(object_sk, :pfx)"), | |
| Limit: aws.Int64(50), | |
| } | |
| fmt.Println("QUERY BUCKET LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var blist []interface{} | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &blist) | |
| if err != nil { | |
| return nil, err | |
| } | |
| umap := make(map[string]interface{}) // place map | |
| uChan := make(chan map[string]interface{}) | |
| for _, pid := range blist { | |
| pkid := fmt.Sprintf("PLACE") | |
| pids := pid.(map[string]interface{}) | |
| skid := pids["place_id"].(string) | |
| go getItemInListGoRoutine(pkid, skid, umap, uChan) | |
| <-uChan | |
| } | |
| close(uChan) | |
| return umap, nil | |
| } | |
| // TODO query placeid from trip | |
| // TODO save places to user bucket list | |
| func (ctrl *DbController) SavePlacesToBucketList(t *Trip, uid string) error { | |
| // fmt.Println("ADD BUCKET ITEM TO TRIP ID", t.ObjectId) | |
| // fmt.Println("ADD BUCKET ITEM TO TRIP SK", t.ObjectSk) | |
| // query user following by userId | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":tid": {S: aws.String(t.ObjectId)}, | |
| ":pfx": {S: aws.String("TRIP-LOCATION-")}, | |
| }, | |
| // IndexName: aws.String("user_idx"), | |
| ProjectionExpression: aws.String("place_id"), | |
| KeyConditionExpression: aws.String("object_id = :tid and begins_with(object_sk, :pfx)"), | |
| Limit: aws.Int64(50), | |
| } | |
| fmt.Println("QUERY PLACE LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var plist []interface{} | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &plist) | |
| if err != nil { | |
| return err | |
| } | |
| // TODO for loop go routine for each placeid | |
| for _, pid := range plist { | |
| // fmt.Println("PLACE ID", pid) | |
| // https://gist.github.com/nevzatalkan/f5c5ef66e88dd446976401967b6731e8 | |
| pids := pid.(map[string]interface{}) | |
| // fmt.Println("PLACE ID", ppid["place_id"]) | |
| // lpkid := fmt.Sprintf("PLACE") | |
| objSk := fmt.Sprintf("BUCKET-ITEM-%s", pids["place_id"]) | |
| if err != nil { | |
| // return nil, err | |
| } | |
| b := &BucketItem{} | |
| b.ObjectId = uid | |
| b.ObjectSk = objSk | |
| b.PlaceId = pids["place_id"].(string) | |
| // b.Name = pids["name"].(string) | |
| b.CreatedBy = uid | |
| b.CreatedAt = time.Now().Format(time.RFC3339) | |
| // b.CreatedAt = t.CreatedAt | |
| go ctrl.SaveItemST(b) | |
| } | |
| return nil | |
| } | |
| func (ctrl *DbController) RemoveFollowingUserST(objId string) (interface{}, error) { | |
| // pk := fmt.Sprintf("FOLLOWING-%s", objId) | |
| // tsk := fmt.Sprintf("USER-%s", objId) | |
| // TODO remove item by pk sk | |
| return nil, nil | |
| } | |
| func (ctrl *DbController) RemoveFollowingTripST(objId string) (interface{}, error) { | |
| // pk := fmt.Sprintf("FOLLOWING-%s", objId) | |
| // tsk := fmt.Sprintf("TRIP-%s", objId) | |
| // TODO remove item by pk sk | |
| return nil, nil | |
| } | |
| func (ctrl *DbController) GetFollowingTripST(userId string) (interface{}, interface{}, error) { | |
| // query triplist following by userId | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":uid": {S: aws.String(userId)}, | |
| ":pfx": {S: aws.String("FOLLOWING-TRIP")}, | |
| }, | |
| // IndexName: aws.String("user_idx"), | |
| KeyConditionExpression: aws.String("object_id = :uid and begins_with(object_sk, :pfx)"), | |
| Limit: aws.Int64(50), | |
| } | |
| fmt.Println("QUERY USER LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var tlist []*Following | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &tlist) | |
| if err != nil { | |
| return nil, nil, err | |
| } | |
| if len(tlist) == 0 { | |
| return nil, nil, err | |
| } | |
| tmap := map[string]*Trip{} // trip map | |
| tChan := make(chan map[string]*Trip) | |
| // query trip | |
| for i := range tlist { | |
| tid := fmt.Sprintf("%v", tlist[i].FollowingID) | |
| // pkid := fmt.Sprintf("TRIP-%s", tid) | |
| skid := fmt.Sprintf("TRIP-DETAIL") | |
| go getTripItemInListGoRoutine(tid, skid, tmap, tChan) | |
| // log.Println("GET USER OUTPUT", <-uChan) | |
| <-tChan | |
| } | |
| cmap := make(map[string]interface{}) // city map | |
| cChan := make(chan map[string]interface{}) | |
| // query city | |
| for _, v := range tmap { | |
| cid := fmt.Sprintf("%v", v.CityRef) // TODO type conversion error | |
| // cid := fmt.Sprintf("%v", vv.CityRef) // TODO type conversion error | |
| pkid := fmt.Sprintf("CITY") | |
| skid := fmt.Sprintf("CITY-%s", cid) | |
| go getItemInListGoRoutine(pkid, skid, cmap, cChan) | |
| // go queryCityInListGoRoutine(cid, cmap, cChan) | |
| // log.Println("GET USER OUTPUT", <-uChan) | |
| <-cChan | |
| } | |
| close(tChan) | |
| close(cChan) | |
| return tmap, cmap, nil | |
| } | |
| func (ctrl *DbController) GetFollowingUserST(userId string) (interface{}, error) { | |
| // query user following by userId | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":uid": {S: aws.String(userId)}, | |
| ":pfx": {S: aws.String("FOLLOWING-USER")}, | |
| }, | |
| // IndexName: aws.String("user_idx"), | |
| KeyConditionExpression: aws.String("object_id = :uid and begins_with(object_sk, :pfx)"), | |
| Limit: aws.Int64(50), | |
| } | |
| fmt.Println("QUERY USER LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var ulist []*Following | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &ulist) | |
| if err != nil { | |
| return nil, err | |
| } | |
| // query user | |
| umap := make(map[string]interface{}) // user map | |
| uChan := make(chan map[string]interface{}) | |
| for i := range ulist { | |
| tid := fmt.Sprintf("%v", ulist[i].FollowingID) | |
| pkid := fmt.Sprintf("USER") | |
| // skid := fmt.Sprintf("USER-%s", tid) | |
| go getItemInListGoRoutine(pkid, tid, umap, uChan) | |
| // go getUserInListGoRoutine(tid, tmap, tChan) | |
| // log.Println("GET USER OUTPUT", <-uChan) | |
| <-uChan | |
| } | |
| close(uChan) | |
| return umap, nil | |
| } | |
| func (ctrl *DbController) QueryLocationListByTripRefST(tripId string) (interface{}, interface{}, error) { | |
| // TODO query location by tripid limit 10 | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":tid": {S: aws.String(tripId)}, | |
| ":idpref": {S: aws.String("TRIP-LOCATION-")}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :tid and begins_with(object_sk, :idpref)"), | |
| Limit: aws.Int64(10), | |
| } | |
| fmt.Println("QUERY TRIP LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var plist []*Location | |
| fmt.Println("TRIP LOCATION LIST ", plist) | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &plist) | |
| if err != nil { | |
| return nil, nil, err | |
| } | |
| if plist == nil { | |
| // TODO query suggestion by tripid limit 10 | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":idpref": {S: aws.String("SUGGESTION-")}, | |
| ":tid": {S: aws.String(tripId)}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :tid and begins_with(object_sk, :idpref)"), | |
| Limit: aws.Int64(10), | |
| } | |
| res, err := ctrl.conn.Query(qInput) | |
| var slist []*Location | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &slist) | |
| if err != nil { | |
| return nil, nil, err | |
| } | |
| // TODO get location in list | |
| smap := make(map[string]interface{}) // location map | |
| schan := make(chan map[string]interface{}) | |
| for _, l := range slist { | |
| pid := l.PlaceId | |
| fmt.Println("PLACE ID ", pid) | |
| lpkid := fmt.Sprintf("PLACE") | |
| // lskid := fmt.Sprintf("PLACE-%s", id) | |
| go getItemInListGoRoutine(lpkid, pid, smap, schan) | |
| <-schan | |
| } | |
| fmt.Println("TRIP SUGGESTION MAP ", smap) | |
| close(schan) | |
| return nil, smap, nil | |
| } | |
| // TODO get location in list | |
| lmap := make(map[string]interface{}) // location map | |
| lchan := make(chan map[string]interface{}) | |
| for _, l := range plist { | |
| pid := l.PlaceId | |
| lpkid := fmt.Sprintf("PLACE") | |
| // lskid := fmt.Sprintf("PLACE-%s", id) | |
| go getItemInListGoRoutine(lpkid, pid, lmap, lchan) | |
| <-lchan | |
| } | |
| fmt.Println("TRIP LOCATION MAP ", lmap) | |
| close(lchan) | |
| return lmap, nil, nil | |
| } | |
| func (ctrl *DbController) GetTripDetailST(tripId string) (interface{}, interface{}, interface{}, interface{}, interface{}, interface{}, error) { | |
| // tpk := fmt.Sprintf("%s", tripId) | |
| tsk := fmt.Sprintf("TRIP-DETAIL") | |
| trip, err := ctrl.GetTripItemST(tripId, tsk) | |
| if err != nil { | |
| // trip not exists | |
| return nil, nil, nil, nil, nil, nil, err | |
| } | |
| fmt.Println("TRIP DETAIL ", trip) | |
| // get user | |
| utpk := fmt.Sprintf("USER") | |
| utsk := fmt.Sprintf("%s", trip.(*Trip).CreatedBy) | |
| user, err := ctrl.GetItemDetailST(utpk, utsk) | |
| if err != nil { | |
| return nil, nil, nil, nil, nil, nil, err | |
| } | |
| // get city | |
| ctpk := fmt.Sprintf("CITY") | |
| ctsk := fmt.Sprintf("CITY-%s", trip.(*Trip).CityRef) | |
| city, err := ctrl.GetItemDetailST(ctpk, ctsk) | |
| if err != nil { | |
| return nil, nil, nil, nil, nil, nil, err | |
| } | |
| // get category | |
| catpk := fmt.Sprintf("CATEGORY") | |
| catsk := fmt.Sprintf("%s", trip.(*Trip).CategoryRef) | |
| cat, err := ctrl.GetItemDetailST(catpk, catsk) | |
| if err != nil { | |
| return nil, nil, nil, nil, nil, nil, err | |
| } | |
| // get location map | |
| locmap, sugmap, err := ctrl.QueryLocationListByTripRefST(tripId) | |
| if err != nil { | |
| return trip, user, city, cat, nil, nil, err | |
| } | |
| return trip, user, city, cat, locmap, sugmap, nil | |
| } | |
| func (ctrl *DbController) QueryCommentST(tripId string) (map[string]interface{}, []*Comment, error) { | |
| // get comment | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":skpref": {S: aws.String("COMMENT")}, | |
| ":tid": {S: aws.String(tripId)}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :tid and begins_with(object_sk, :skpref)"), | |
| Limit: aws.Int64(30), | |
| } | |
| fmt.Println("QUERY COMMENT LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var clist []*Comment | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &clist) | |
| if err != nil { | |
| return nil, nil, err | |
| } | |
| log.Println("QUERY COMMENT RESULT", clist) | |
| // get associated user | |
| umap := make(map[string]interface{}) | |
| uChan := make(chan map[string]interface{}) | |
| for j := range clist { | |
| uid := clist[j].CreatedBy | |
| // utpk := fmt.Sprintf("USER-%s", uid) | |
| // utsk := fmt.Sprintf("DETAIL-%s", uid) | |
| go getItemInListGoRoutine("USER", uid, umap, uChan) | |
| <-uChan | |
| } | |
| close(uChan) | |
| log.Println("QUERY COMMENT RESULT", umap) | |
| return umap, clist, nil | |
| } | |
| // TODO get place count by trip | |
| func (ctrl *DbController) QueryTopTripST(cityId string) (interface{}, interface{}, interface{}, error) { | |
| cityPref := fmt.Sprintf("CITY-%s", cityId) | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":tpx": {S: aws.String("TRIP-")}, | |
| ":cid": {S: aws.String(cityPref)}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :cid and begins_with(object_sk, :tpx)"), | |
| // projection tripid, description, createdby | |
| Limit: aws.Int64(10), | |
| } | |
| fmt.Println("QUERY TRIP LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var tlist []*Trip | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &tlist) | |
| if err != nil { | |
| return nil, nil, nil, err | |
| } | |
| // TODO run get user goroutines | |
| umap := make(map[string]interface{}) | |
| uChan := make(chan map[string]interface{}) | |
| tmap := map[string]*Trip{} | |
| tChan := make(chan map[string]*Trip) | |
| cmap := make(map[string]int) | |
| cChan := make(chan map[string]int) | |
| for i := range tlist { | |
| uid := tlist[i].CreatedBy | |
| tid := tlist[i].ObjectSk | |
| // tpk := fmt.Sprintf("TRIP-", tid) | |
| go getItemInListGoRoutine("USER", uid, umap, uChan) | |
| go getTripItemInListGoRoutine(tid, "TRIP-DETAIL", tmap, tChan) | |
| go queryPlaceCountGoRoutine(tid, cmap, cChan) | |
| <-cChan | |
| <-uChan | |
| <-tChan | |
| } | |
| close(cChan) | |
| close(uChan) | |
| close(tChan) | |
| log.Println("GET USER LIST OUTPUT", tlist) | |
| log.Println("GET USER LIST OUTPUT", umap) | |
| return tmap, umap, cmap, nil | |
| } | |
| func (ctrl *DbController) QueryTripListByCityST(cityId string) (interface{}, interface{}, interface{}, error) { | |
| cityPref := fmt.Sprintf("CITY-%s", cityId) | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":tpx": {S: aws.String("TRIP-")}, | |
| ":cid": {S: aws.String(cityPref)}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :cid and begins_with(object_sk, :tpx)"), | |
| // projection tripid, description, createdby | |
| } | |
| fmt.Println("QUERY TRIP LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var tlist []*Trip | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &tlist) | |
| if err != nil { | |
| return nil, nil, nil, err | |
| } | |
| // TODO get location count | |
| // TODO run get user goroutines | |
| umap := make(map[string]interface{}) | |
| uChan := make(chan map[string]interface{}) | |
| tmap := map[string]*Trip{} | |
| tChan := make(chan map[string]*Trip) | |
| cmap := make(map[string]int) | |
| cChan := make(chan map[string]int) | |
| for i := range tlist { | |
| uid := tlist[i].CreatedBy | |
| tid := tlist[i].ObjectSk | |
| // tpk := fmt.Sprintf("TRIP-", tid) | |
| go getItemInListGoRoutine("USER", uid, umap, uChan) | |
| go getTripItemInListGoRoutine(tid, "TRIP-DETAIL", tmap, tChan) | |
| go queryPlaceCountGoRoutine(tid, cmap, cChan) | |
| <-cChan | |
| <-uChan | |
| <-tChan | |
| } | |
| close(cChan) | |
| close(uChan) | |
| close(tChan) | |
| log.Println("GET USER LIST OUTPUT", tlist) | |
| log.Println("GET USER LIST OUTPUT", umap) | |
| log.Println("GET USER LIST OUTPUT", cmap) | |
| return tmap, umap, cmap, nil | |
| } | |
| func (ctrl *DbController) QueryTripListByUserST(userId string) (interface{}, map[string]interface{}, error) { | |
| qInput := &dynamodb.QueryInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":uid": {S: aws.String(userId)}, | |
| ":idpref": {S: aws.String("TRIP-")}, | |
| }, | |
| KeyConditionExpression: aws.String("object_id = :uid and begins_with(object_sk, :idpref)"), | |
| // projection tripid, description, createdby | |
| // ProjectionExpression: aws.String("city_id"), | |
| } | |
| fmt.Println("QUERY TRIP LIST INPUT", qInput) | |
| res, err := ctrl.conn.Query(qInput) | |
| var tlist []*Trip | |
| err = dynamodbattribute.UnmarshalListOfMaps(res.Items, &tlist) | |
| if err != nil { | |
| return nil, nil, err | |
| } | |
| // TODO run get city goroutines | |
| cmap := make(map[string]interface{}) | |
| cChan := make(chan map[string]interface{}) | |
| tmap := map[string]*Trip{} | |
| tChan := make(chan map[string]*Trip) | |
| for i := range tlist { | |
| pid := tlist[i].CityRef | |
| pk := fmt.Sprintf("CITY") | |
| sk := fmt.Sprintf("CITY-%s", pid) | |
| tid := tlist[i].ObjectSk | |
| go getItemInListGoRoutine(pk, sk, cmap, cChan) | |
| go getTripItemInListGoRoutine(tid, "TRIP-DETAIL", tmap, tChan) | |
| <-cChan | |
| <-tChan | |
| } | |
| close(cChan) | |
| close(tChan) | |
| log.Println("GET USER LIST OUTPUT", cmap) | |
| log.Println("GET USER LIST OUTPUT", tlist) | |
| return tmap, cmap, nil | |
| } | |
| func (ctrl *DbController) IncrementTripLike(tid string) error { | |
| oldItemKeys := map[string]*dynamodb.AttributeValue{ | |
| "object_id": {S: aws.String(tid)}, // hash key | |
| "object_sk": {S: aws.String("TRIP-DETAIL")}, // hash key | |
| } | |
| updateInput := &dynamodb.UpdateItemInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| Key: oldItemKeys, // match key attributes per table definition | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":one": {N: aws.String(fmt.Sprintf("%d", 1))}, // set new value | |
| }, | |
| ConditionExpression: aws.String("attribute_exists(object_id)"), | |
| ReturnValues: aws.String("UPDATED_NEW"), // enum of ReturnValue class UPDATED_NEW ALL_NEW ALL_OLD | |
| UpdateExpression: aws.String("ADD like_counter :one"), // SET,REMOVE the attribute to update | |
| } | |
| result, err := ctrl.conn.UpdateItem(updateInput) | |
| if err != nil { | |
| return err | |
| } | |
| log.Printf("UPDATE RESULT %s", result.Attributes) | |
| var out interface{} | |
| err = dynamodbattribute.UnmarshalMap(result.Attributes, &out) | |
| if err != nil { | |
| return err | |
| } | |
| return nil | |
| } | |
| func (ctrl *DbController) UpdateUserBioST(newUser *User) (interface{}, error) { | |
| oldItemKeys := map[string]*dynamodb.AttributeValue{ | |
| "object_id": {S: aws.String("USER")}, // hash key | |
| "object_sk": {S: aws.String(newUser.ObjectId)}, // hash key | |
| } | |
| updateInput := &dynamodb.UpdateItemInput{ | |
| TableName: aws.String("tasl_app_main"), | |
| Key: oldItemKeys, // match key attributes per table definition | |
| ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ | |
| ":B": {S: aws.String(newUser.Bio)}, // set new value | |
| }, | |
| ExpressionAttributeNames: map[string]*string{ | |
| "#bio": aws.String("bio"), | |
| }, | |
| ConditionExpression: aws.String("attribute_exists(object_id)"), | |
| ReturnValues: aws.String("UPDATED_NEW"), // enum of ReturnValue class UPDATED_NEW ALL_NEW ALL_OLD | |
| UpdateExpression: aws.String("set #bio = :B"), // SET,REMOVE the attribute to update | |
| } | |
| log.Printf("UPDATE USER INPUT %v", updateInput) | |
| result, err := ctrl.conn.UpdateItem(updateInput) | |
| if err != nil { | |
| return nil, err | |
| } | |
| log.Printf("UPDATE RESULT %s", result.Attributes) | |
| var out interface{} | |
| err = dynamodbattribute.UnmarshalMap(result.Attributes, &out) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return out, nil | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment