Instantly share code, notes, and snippets.
Created
April 18, 2018 11:18
-
Save toVersus/ac0bdc3a858e7d1e4e17aed4623a72a0 to your computer and use it in GitHub Desktop.
[Language Processing 100 Essentials] #63: Insert object into value on KVS
This file contains 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 ( | |
"bufio" | |
"encoding/json" | |
"flag" | |
"fmt" | |
"io" | |
"os" | |
"github.com/go-redis/redis" | |
) | |
type Artist struct { | |
ID int `json:"id"` | |
GID string `json:"gid"` | |
Name string `json:"name"` | |
SortName string `json:"sort_name"` | |
Area string `json:"area"` | |
Aliases []*Aliase `json:"aliases"` | |
Begin *Begin `json:"begin"` | |
End *End `json:"end"` | |
Tags []*Tag `json:"tags"` | |
Rating *Rating `json:"rating"` | |
} | |
type Artists []*Artist | |
func (artists Artists) rpushTags(client *redis.Client) error { | |
for _, artist := range artists { | |
if len(artist.Tags) == 0 { | |
continue | |
} | |
for _, tag := range artist.Tags { | |
err := client.RPush(artist.Name, tag).Err() | |
if err != nil { | |
return fmt.Errorf("could not push the lists\n %s", err) | |
} | |
} | |
} | |
return nil | |
} | |
type Aliase struct { | |
Name string `json:"name"` | |
SortName string `json:"sort_name"` | |
} | |
type Begin struct { | |
Year int `json:"year"` | |
Month int `json:"month"` | |
Date int `json:"date"` | |
} | |
type End struct { | |
Year int `json:"year"` | |
Month int `json:"month"` | |
Date int `json:"date"` | |
} | |
type Tag struct { | |
Count int `json:"count"` | |
Value string `json:"value"` | |
} | |
// MarshalBinary interface must be implemeted to encode the Tag type to json format and set as list-typed value: | |
// https://stackoverflow.com/questions/44771474/how-to-set-array-document-into-redis-in-golang | |
func (t Tag) MarshalBinary() ([]byte, error) { | |
return json.Marshal(t) | |
} | |
type Rating struct { | |
Count int `json:"count"` | |
Value int `json:"value"` | |
} | |
func main() { | |
var filepath, artistName string | |
flag.StringVar(&filepath, "file", "", "specify a file path") | |
flag.StringVar(&filepath, "f", "", "specify a file path") | |
flag.StringVar(&artistName, "name", "", "specify the artist name") | |
flag.StringVar(&artistName, "n", "", "specify the artist name") | |
flag.Parse() | |
artists, err := readJSON(filepath) | |
if err != nil { | |
fmt.Println(err) | |
os.Exit(1) | |
} | |
client, err := newRedisClient() | |
if err != nil { | |
fmt.Println(err) | |
os.Exit(1) | |
} | |
err = artists.rpushTags(client) | |
if err != nil { | |
fmt.Println(err) | |
os.Exit(1) | |
} | |
tags, err := getTags(client, artistName) | |
if err != nil { | |
fmt.Println(err) | |
os.Exit(1) | |
} | |
for _, tag := range tags { | |
fmt.Printf("tag.count: %d, tag.value: %s\n", tag.Count, tag.Value) | |
} | |
} | |
func getTags(client *redis.Client, artistName string) ([]Tag, error) { | |
rets, err := client.LRange(artistName, 0, -1).Result() | |
if err != nil { | |
return nil, fmt.Errorf("could not get the lists\n %s", err) | |
} | |
if err == redis.Nil { | |
return nil, fmt.Errorf("could not find the value...%s", artistName) | |
} | |
tag, tags := Tag{}, []Tag{} | |
buf := []byte{} | |
for _, ret := range rets { | |
buf = []byte(ret) | |
json.Unmarshal(buf, &tag) | |
tags = append(tags, tag) | |
} | |
return tags, nil | |
} | |
func readJSON(path string) (Artists, error) { | |
f, err := os.Open(path) | |
if err != nil { | |
return nil, fmt.Errorf("could not open a file: %s\n %s", path, err) | |
} | |
defer f.Close() | |
var artists Artists | |
reader := bufio.NewReader(f) | |
for { | |
artist := Artist{} | |
buf, readErr := reader.ReadBytes('\n') | |
if (readErr != nil) && (readErr != io.EOF) { | |
panic(err) | |
} | |
if err = json.Unmarshal(buf, &artist); err != nil && readErr != io.EOF { | |
fmt.Print("could not parse json file.") | |
break | |
} | |
artists = append(artists, &artist) | |
if readErr == io.EOF { | |
break | |
} | |
} | |
return artists, nil | |
} | |
func newRedisClient() (*redis.Client, error) { | |
client := redis.NewClient(&redis.Options{ | |
Addr: "127.0.0.1:6379", | |
Password: "", | |
DB: 0, | |
}) | |
pong, err := client.Ping().Result() | |
if err != nil { | |
return nil, fmt.Errorf("could not connect to redis\n %s", err) | |
} | |
fmt.Println(pong, err) | |
return client, nil | |
} |
This file contains 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 ( | |
"os" | |
"testing" | |
"github.com/go-test/deep" | |
) | |
var getTagsTests = []struct { | |
name string | |
file string | |
text string | |
artistName string | |
want []Tag | |
}{ | |
{ | |
name: "should get the tags", | |
file: "./fulltext-test.json", | |
text: `{"name": "WIK▲N", "tags": [{"count": 1, "value": "sillyname"}], "sort_name": "WIK▲N", "ended": true, "gid": "8972b1c1-6482-4750-b51f-596d2edea8b1", "id": 805192} | |
{"name": "Gustav Ruppke", "sort_name": "Gustav Ruppke", "ended": true, "gid": "b4f76788-7e6f-41b7-ac7b-dfb67f66282e", "type": "Person", "id": 578352}`, | |
artistName: "WIK▲N", | |
want: []Tag{ | |
Tag{Count: 1, Value: "sillyname"}, | |
}, | |
}, | |
} | |
func TestGetTags(t *testing.T) { | |
for _, testcase := range getTagsTests { | |
t.Log(testcase.name) | |
f, err := os.Create(testcase.file) | |
if err != nil { | |
t.Errorf("could not create a file: %s\n %s\n", testcase.file, err) | |
} | |
f.WriteString(testcase.text) | |
f.Close() | |
artists, err := readJSON(testcase.file) | |
if err != nil { | |
t.Errorf("could not parse a JSON file: %s\n %s\n", testcase.file, err) | |
} | |
client, err := newRedisClient() | |
if err != nil { | |
t.Error(err) | |
} | |
err = artists.rpushTags(client) | |
if err != nil { | |
t.Error(err) | |
} | |
results, err := getTags(client, testcase.artistName) | |
if err != nil { | |
t.Error(err) | |
} | |
if diff := deep.Equal(results, testcase.want); diff != nil { | |
t.Error(diff) | |
} | |
for _, artist := range artists { | |
_, err := client.Del(artist.Name).Result() | |
if err != nil { | |
t.Error(err) | |
} | |
} | |
if err = os.Remove(testcase.file); err != nil { | |
t.Errorf("could not delete a file: %s\n %s\n", testcase.file, err) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment