Skip to content

Instantly share code, notes, and snippets.

@toVersus
Created April 18, 2018 11:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toVersus/ac0bdc3a858e7d1e4e17aed4623a72a0 to your computer and use it in GitHub Desktop.
Save toVersus/ac0bdc3a858e7d1e4e17aed4623a72a0 to your computer and use it in GitHub Desktop.
[Language Processing 100 Essentials] #63: Insert object into value on KVS
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
}
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