Redigo: Ajout de la prise en charge du hachage

Créé le 30 mars 2013  ·  7Commentaires  ·  Source: gomodule/redigo

Je n'ai pas pu obtenir l'équivalent Go + redigo de

HMSET myhash field1 "Hello" field2 "World"

pour fonctionner ("ERR mauvais nombre d'arguments pour la commande 'hmset'"). La prise en charge du hachage natif serait bien pour contourner ce problème et fournir des fonctions pratiques.

Commentaire le plus utile

Voici un autre exemple qui utilise struct au lieu de map. Cet exemple stocke les données dans le même format que les exemples précédents.

package main

import (
    "github.com/garyburd/redigo/redis"
    "log"
)

type Stock struct {
    CompanyName string `redis:"company_name"`
    OpenPrice   string `redis:"open_price"`
    AskPrice    string `redis:"ask_price"`
    ClosePrice  string `redis:"close_price"`
    BidPrice    string `redis:"bid_price"`
}

func main() {
    conn, err := redis.Dial("tcp", ":6379")
    if err != nil {
        log.Fatalf("Couldn't connect to Redis: %v\n", err)
    }
    defer conn.Close()

    stockData := map[string]*Stock{
        "GOOG": &Stock{CompanyName: "Google Inc.", OpenPrice: "803.99", AskPrice: "795.50", ClosePrice: "802.66", BidPrice: "793.36"},
        "MSFT": &Stock{AskPrice: "N/A", OpenPrice: "28.30", CompanyName: "Microsoft Corpora", BidPrice: "28.50", ClosePrice: "28.37"},
    }

    for sym, row := range stockData {
        if _, err := conn.Do("HMSET", redis.Args{sym}.AddFlat(row)...); err != nil {
            log.Fatal(err)
        }
    }

    for sym := range stockData {
        values, err := redis.Values(conn.Do("HGETALL", sym))
        if err != nil {
            log.Fatal(err)
        }
        var stock Stock
        if err := redis.ScanStruct(values, &stock); err != nil {
            log.Fatal(err)
        }
        log.Printf("%s: %+v", sym, &stock)
    }
}

Tous les 7 commentaires

Redigo peut exécuter n'importe quelle commande, y compris HMSET. Pouvez-vous partager la ligne de code où vous invoquez HMSET ?

package main

import (
    "fmt"
    "github.com/garyburd/redigo/redis"
    "log"
)

var (
    conn redis.Conn
)

// Connect to Redis
func init() {
    var err error
    conn, err = redis.Dial("tcp", ":6379")
    if err != nil {
        log.Fatalf("Couldn't connect to Redis: %v\n", err)
    }
}

func main() {
    defer conn.Close()

    stockData := map[string]map[string]string{
        "GOOG": {"company_name":"Google Inc.", "open_price":"803.99", "ask_price":"795.50", "close_price":"802.66", "bid_price":"793.36"},
        "MSFT": {"ask_price":"N/A", "open_price":"28.30", "company_name":"Microsoft Corpora", "bid_price":"28.50", "close_price":"28.37"},
    }

    conn.Send("HMSET", "stocks")
    // conn.Send("HMSET")
    // conn.Send("stocks")
    // var cmd []interface{}
    for sym, row := range stockData {
        for colName, val := range row {
            key := sym + ":" + colName
            // cmd = append(cmd, key, val)
            conn.Send(key, val)
        }
    }
    // conn.Send("HMSET", cmd...)
    reply, err := conn.Do("EXEC")
    if err != nil {
        log.Fatalf("Error setting hash: %v\n", err)
    }
    fmt.Printf("reply == %+v\n", reply)
}

Les commentaires révèlent les autres versions que j'ai également essayées, telles que l'envoi (presque) de toutes les commandes à la fois avec conn.Send("HMSET", cmd...) . conn.Send("HMSET", "stocks", cmd...) ne compile pas.

Une idée de ce que je fais mal?

Les exemples suivants montrent comment créer un hachage pour chaque symbole.

package main

import (
    "github.com/garyburd/redigo/redis"
    "log"
)

func main() {
    conn, err := redis.Dial("tcp", ":6379")
    if err != nil {
        log.Fatalf("Couldn't connect to Redis: %v\n", err)
    }
    defer conn.Close()

    stockData := map[string]map[string]string{
        "GOOG": {"company_name": "Google Inc.", "open_price": "803.99", "ask_price": "795.50", "close_price": "802.66", "bid_price": "793.36"},
        "MSFT": {"ask_price": "N/A", "open_price": "28.30", "company_name": "Microsoft Corpora", "bid_price": "28.50", "close_price": "28.37"},
    }

    // Example 1: Write command arguments out explicitly.

    for sym, row := range stockData {
        if _, err := conn.Do("HMSET", sym,
            "company_name", row["company_name"],
            "open_price", row["open_price"],
            "ask_price", row["ask_price"],
            "bid_price", row["bid_price"]); err != nil {
            log.Fatal(err)
        }
    }

    printAndDel(conn, "example 1", stockData)

    // Example 2: Construct command arguments using range over a row map.

    for sym, row := range stockData {
        args := []interface{}{sym}
        for k, v := range row {
            args = append(args, k, v)
        }
        if _, err := conn.Do("HMSET", args...); err != nil {
            log.Fatal(err)
        }
    }

    printAndDel(conn, "example 2", stockData)

    // Example 3: Construct command arguments using Redigo helper function.

    for sym, row := range stockData {
        if _, err := conn.Do("HMSET", redis.Args{sym}.AddFlat(row)...); err != nil {
            log.Fatal(err)
        }
    }

    printAndDel(conn, "example 3", stockData)
}

func printAndDel(conn redis.Conn, message string, stockData map[string]map[string]string) {
    log.Print(message)
    for sym := range stockData {
        values, err := redis.Values(conn.Do("HGETALL", sym))
        if err != nil {
            log.Fatal(err)
        }
        log.Print(sym)
        for i := 0; i < len(values); i += 2 {
            log.Printf("  %s: %s", values[i], values[i+1])
        }
    }
    for sym := range stockData {
        if _, err := conn.Do("DEL", sym); err != nil {
            log.Fatal(err)
        }
    }
}

Voici un autre exemple qui utilise struct au lieu de map. Cet exemple stocke les données dans le même format que les exemples précédents.

package main

import (
    "github.com/garyburd/redigo/redis"
    "log"
)

type Stock struct {
    CompanyName string `redis:"company_name"`
    OpenPrice   string `redis:"open_price"`
    AskPrice    string `redis:"ask_price"`
    ClosePrice  string `redis:"close_price"`
    BidPrice    string `redis:"bid_price"`
}

func main() {
    conn, err := redis.Dial("tcp", ":6379")
    if err != nil {
        log.Fatalf("Couldn't connect to Redis: %v\n", err)
    }
    defer conn.Close()

    stockData := map[string]*Stock{
        "GOOG": &Stock{CompanyName: "Google Inc.", OpenPrice: "803.99", AskPrice: "795.50", ClosePrice: "802.66", BidPrice: "793.36"},
        "MSFT": &Stock{AskPrice: "N/A", OpenPrice: "28.30", CompanyName: "Microsoft Corpora", BidPrice: "28.50", ClosePrice: "28.37"},
    }

    for sym, row := range stockData {
        if _, err := conn.Do("HMSET", redis.Args{sym}.AddFlat(row)...); err != nil {
            log.Fatal(err)
        }
    }

    for sym := range stockData {
        values, err := redis.Values(conn.Do("HGETALL", sym))
        if err != nil {
            log.Fatal(err)
        }
        var stock Stock
        if err := redis.ScanStruct(values, &stock); err != nil {
            log.Fatal(err)
        }
        log.Printf("%s: %+v", sym, &stock)
    }
}

De très bons exemples, merci ! J'ai lu un peu plus et il semble que Redis ne prend pas en charge les hachages imbriqués, donc je suppose que ce que j'essayais de faire ne fonctionnera pas : créer un hachage Redis qui contient un autre hachage des symboles aux données de stock. Je peux essayer le hack probablement assez bon de stocker du JSON sous forme de chaîne puisque c'est vraiment ce dont j'ai besoin.

D'une manière ou d'une autre, je pourrai faire en sorte que cela fonctionne, surtout avec les exemples que vous avez donnés. Merci encore!

Les hachages imbriqués ne sont pas pris en charge. Le court et gratuit The Little Redis Book donne un bon aperçu des types pris en charge par Redis.

Il est courant de stocker JSON dans Redis. Si vous n'accédez aux données qu'à partir de Go, l' encodage/gob est une autre bonne option pour stocker les données imbriquées.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

samwhitecoull picture samwhitecoull  ·  3Commentaires

Serhioromano picture Serhioromano  ·  7Commentaires

lovegnep picture lovegnep  ·  18Commentaires

garyburd picture garyburd  ·  23Commentaires

Wang-Kai picture Wang-Kai  ·  4Commentaires