How to print specific fields from firebase database - firebase

I am a complete firebase newbie, but basically my situation is this I am collecting weather data and storing it in firebase like so:
{
"-Kw2H2dbJKZbbg-6LA6b": {
"date": "10/9/2017",
"data": "filler test data",
}
}
And then I will display this info to my website. I am using Go with firego as my backend and I am wondering how could I query my db and print any individual field. For example I wish to display the date
"date": "10/9/2017"
Just in general how can this be done. Any help is much appreciated!

If the query result is stored as map[string]interface{} then iterate over the results as:
//queryResults := ...
for _, val := range queryResults {
//test whether vmap is an object/not
vmap, ok := val.(map[string]interface{})
if !ok {
continue
}
//vmap contains {"date":..., "data":...}
field := "date"
if v, ok := vmap[field]; ok {
fmt.Printf("%s: %v\n", field, v)
}
}
If you don't know the object's hierarchy, you can implement a kind of find function to search for a specific key/field from queryResults. See https://stackoverflow.com/a/45757396/6207052.

Related

Why is DynamoDB adding a NULL suffix to attribute names?

I've been working on a toy project and noticed that dynamo added a (NULL) suffix in two of my attribute names. I had not noticed before, so I assume it must have happened after one of my code changes. I could not find any reference to this behavior online.
The script I'm running is a simple PutItem got from the official Dynamodb documentation, where I insert a few mock users in a table.
func InsertModel(m interface{}) error {
av, err := dynamodbattribute.MarshalMap(m)
if err != nil {
return fmt.Errorf("handlers: Got error marshalling map: %v", err)
}
input := &dynamodb.PutItemInput{
Item: av,
TableName: aws.String(appTableName),
ConditionExpression: aws.String("attribute_not_exists(PK) AND attribute_not_exists(SK)"),
}
_, err = svc.PutItem(input)
if err != nil {
return fmt.Errorf("handlers: Got error calling PutItem: %v", err)
}
return nil
}
m (user mock data) has all fields type string:
UserModel{PK: "910cc6d8-b7e2-dfg6-d8d4-sh6d0e3fde6b", SK: "user_info", Name: "bla", ImageURI: "aaa"},
When I remove the fields "Name" and "ImageURI", the PutItem inserts a boolean true to the field value as seen below.
Here is the value in av after the MarshalMap operation.
with populated "Name" and "ImageURI" fields:
map[ImageURI:{
S: "aaa"
} Name:{
S: "bla"
} PK:{
S: "910cc6d8-b7e2-dfg6-d8d4-sh6d0e3fde6b"
} SK:{
S: "user_info"
}]
and here without "Name" and "ImageURI" as in UserModel{PK: "910cc6d8-b7e2-dfg6-d8d4-sh6d0e3fde6b", SK: "user_info"}
map[ImageURI:{
NULL: true
} Name:{
NULL: true
} PK:{
S: "910cc6d8-b7e2-dfg6-d8d4-sh6d0e3fde6b"
} SK:{
S: "user_info"
}]
I have tried to delete all the records from the table and insert again but the behavior continues. Also, I did the same process for an int type attribute (inserting the object with the int attribute populated and not populated) and I get 0 when it's not populated (which is what I'd expect). I tried replicating this with a different string type attribute, and I get the same behavior (true when empty), but the attribute name doesn't get the suffix NULL.
So in summary, it seems this behavior is mostly happening with type string in my case, and I only get a NULL suffix in the attributes "Name" and "ImageURI", but not on the other string attribute I've tried (nor the int one).
I had the same issue for one of the fields of my table items.
For that field I was doing an update using the NameMap option, useful when you want to use a name that, for some other reasons, is reserved by dynamo.
I just tried not to use the NameMap option, giving another name for my field, and that suffix disappeared.
I hope my experience could be somehow helpful.
Regards
Option A
The dynamodbattribute.MarshalMap method reads json struct tags if present. By adding omitempty it will leave the attribute off of the item. Then when reading it back later, it will default to the empty value in the struct.
type Foo struct {
Bar string `json:"bar,omitempty"`
}
Option B
You can explicitly set empty struct values by either creating your own dynamodb.AttributeValue or implement the marshaller interface on your struct. For example:
item := map[string]*dynamodb.AttributeValue{
"Foo": {
S: aws.String("")
}
}
Making the (NULL) suffix to go away
After deleting all the rows containing a NULL value in a column with the (NULL) suffix, it seems to take some time for the suffix to go away from the AWS UI. When I tested this, it took roughly 12 hours.
Discussion
Continue the discussion of null behaviors on github.
https://github.com/aws/aws-sdk-go/pull/2419
https://github.com/aws/aws-sdk-go/issues?q=MarshalMap+null

Get a value from map stored in struct

I have a trouble for gonna get a value from map stored in struct. Please, look at the next part of code (some strings skipped):
type Settings struct {
...
LcInfoData *[]LcInfodb
LcInfoLog *MapLcInfoLL
}
type MapLcInfoLL map[string]LcInfoLL
type LcInfoLL struct {
EnableLog string
FileLogPtr *os.File
}
...
func updLogInfo(cnf *Settings)(err) {
for _, t := range *cnf.LcInfoData {
fpPtr, err := logInit(t.FilepLog);
if err != nil {
exitMsg(1, err.Error());
}
lcMapVal := LcInfoLL{EnableLog: t.EnableLog, FileLogPtr: fpPtr}
lcMap[t.LocationID] = lcMapVal
}
cnf.uLcInfoLog(&lcMap) // at the end
...
}
At the end I got filled structure for using in another function (it's global settings). But. I can't get an access to elements inside a map (which stored in structure). I mean something like that:
v := *cnf.LcInfoLog["index"]
log.Println("ABOUT LOCATION: ", v.FileLogPtr)
Can you help me?
Thank you!

storing datastore tags efficiently (for get by tags purposes)

I've often encountered a situation where I have something like this:
type Article struct {
Title string
User string
Content []byte
Tags []string
}
Where I want to be able to perform query tasks like this:
var articles []Article
query := datastore.NewQuery("Article")
for _, filter := range filters {
if filter.User != "" {
query = query.Filter("User =", filter.User)
}
// how to do if for finding tags
}
keys, err := DatastoreClient().GetAll(ctx, query, &articles)
if err != nil {
return nil, err
}
return articles, nil
Let's say an article have the following tags []string{"golang", "ruby", "python", "programming"} and I want to retrieve all articles that contain the tags golang and programming, how could I efficiently achieve this?
Search in array in datastore with usage of equal sign works as contains.
https://cloud.google.com/datastore/docs/concepts/queries#properties_with_array_values_can_behave_in_surprising_ways
That means, that you need to make a query with two equal filters by this property.
Example on GQL.
SELECT * FROM Article WHERE Tags = "golang" AND Tags = "prgramming".
If Tags is an array, equal will behave as contains. That it. All the trick.

Golang, how to use a struct to write JSON response over HTTP?

The Goal:
Using github.com/neelance/graphql-go starwars example, I'm trying to write a JSON response to my ReactJS client. That struct stuff is completely new for me, Golang as well btw.
The question:
What should data variable be in order to get the appropriate response to the following example GraphQL query?
query clientQuery {
character(id: 1000) {
name
appearsIn
}
}
Additional info:
From what I've read here and there, data must be some kind of struct. I've got plenty of structs available in the example (see starwars.go below).
The Code to be modified (main.go):
package main
import (
"encoding/json"
"log"
"net/http"
"github.com/neelance/graphql-go"
"github.com/neelance/graphql-go/example/starwars"
"github.com/neelance/graphql-go/relay"
)
var schema *graphql.Schema
func init() {
schema = graphql.MustParseSchema(starwars.Schema, &starwars.Resolver{})
}
func main() {
port := ":8080"
log.Printf(`GraphQL server starting up on http://localhost%v`, port)
http.Handle("/query", &relay.Handler{Schema: schema})
http.HandleFunc("/graphql", func(w http.ResponseWriter, r *http.Request) {
// THIS IS SUPER WRONG, data should be something
// like data := starwars.Resolver{} or so?
data := `{"data":{"character":{"name":"Luke Skywalker","appearsIn":["NEWHOPE","EMPIRE","JEDI"]}}}`
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(data)
})
log.Fatal(http.ListenAndServe(port, nil))
}
REFERENCE 1 - starwars.go
REFERENCE 2 - relay.go
You question is a bit confusing. You are asking about JSON, but your wanted response is not in a valid JSON format: It looks like you added unrelated GraphQL information.
I am not sure if this is an question about GraphQL or JSON. I will try to answer it anyway.
Your example data looks like this, therefore I assume that is the result you want to generate:
data := `{"data":{"character":{"name":"Luke Skywalker","appearsIn":["NEWHOPE","EMPIRE","JEDI"]}}}`
A clean way to make Go generate a proper JSON is to create Structs which contain the data:
type Response struct {
Data Data `json:"data"`
}
type Data struct {
Character Character `json:"characer"`
}
type Character struct {
Name string `json:"name"`
AppearsIn []string `json:"appearsIn"`
}
Then you can define the data like this:
data := Response{
Data: Data{
Character: Character{
Name: "Luke Skywalker",
AppearsIn: []string{"NEWHOPE", "EMPIRE", "JEDI"},
},
},
}
Perhaps this question isn't about JSON rather than GraphQL. In this case you need to clarify your question.
References
Details about JSON tags (ie json:".."): https://golang.org/pkg/encoding/json/#Marshal
Example with Structs: https://gobyexample.com/structs
Here is a simpler example, which would have helped me if it had been here.
type Password struct {
Password string `json:"password"`
}
func keyHandler(w http.ResponseWriter, r *http.Request) {
response := Password{"password"}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(response)
}

go lang construct map based on filter criteria

I have below structures
type ModuleList []Module
type Module struct {
Id string
Items []Item
Env map[string]string
}
type Item struct {
Id string
Host string
}
I have a service which returns ModuleList; but I would like to create a function which can group ModuleList based on Module Env key value and return map[string]ModuleList or map[string]*Module
Can i have any sample function which does this ?
I had tried doing this
appsByGroup := make(map[string]ModuleList)
for _, app := range apps {
if _, ok := app.Env["APP_GROUP"]; ok {
appGroup := app.Env["APP_GROUP"]
appsByGroup[appGroup] = app
}
}
; but not quite sure how to add element to an array
If you want to group all the Modules by a APP_GROUP then you are pretty much correct. You are just not appending to the slice correctly:
appsByGroup := make(map[string]ModuleList)
for _, app := range apps {
if _, ok := app.Env["APP_GROUP"]; ok {
appGroup := app.Env["APP_GROUP"]
// app is of type Module while in appsGroup map, each string
// maps to a ModuleList, which is a slice of Modules.
// Hence your original line
// appsByGroup[appGroup] = app would not compile
appsByGroup[appGroup] = append(appsByGroup[appGroup], app)
}
}
Now you can access all the Modules (stored in a slice) in a group by using:
// returns slice of modules (as ModuleList) with
// Env["APP_GROUP"] == group
appGroups[group]

Resources