Closed clanstyles closed 8 years ago
Yes. Please have a look at GetObject
and PutObject
methods in Client
. You can find a few examples in Object Tests.
I've tried using PutObject from Client.
I error out with "panic: Value type 'Page' not supported" - Page is a struct.
Please share a code snippet so that I can help.
I was able to figure out the panic, it was because of how I registered the object.
How are keys supposed to be managed? Should I attach a key as the "Id" to the record? Should I just assume my own string then create the key each time with NewKey before referencing it?
Thank you
You need to create a Key
yourself and pass it to the Get/PutObject
methods.
Keys can get quite complex if they are composite, and unfortunately there's no easy or universal way of doing it automatically that supports all use cases.
Hi khaf, I'd like to follow up asking if my example is correct.
type aeroRepo struct {
client *aerospike.Client
qp *aerospike.QueryPolicy
}
func NewAeroRepo(c *aerospike.Client) aeroRepo {
return aeroRepo{
client: c,
qp: aerospike.NewQueryPolicy(),
}
}
func (c aeroRepo) Get(addr string) (ipAddr *IPAddress, err error) {
var key *aerospike.Key
key, err = aerospike.NewKey(namespace, set, addr)
if err != nil {
return
}
err = c.client.GetObject(nil, key, ipAddr)
return
}
func (c aeroRepo) Save(ipAddr *IPAddress) (err error) {
var key *aerospike.Key
key, err = aerospike.NewKey(namespace, set, ipAddr.IPAddress)
if err != nil {
return
}
err = c.client.PutObject(nil, key, ipAddr)
return
}
type IPAddress struct {
IPAddress string `as:"ipaddress"`
ReverseDNS string `as:"rdns"`
Service int `as:"service"`
Created time.Time `as:"created"`
}
I'm having an issue with this example. PutObject seems to work fine, looking at the data with aql looks fine, the GetObject is crashing.
panic: reflect: call of reflect.Value.Type on zero Value
goroutine 21 [running]:
reflect.Value.Type(0x0, 0x0, 0x0, 0x0, 0x0)
/usr/lib/go/src/reflect/value.go:1664 +0x7b
gopkg.in/aerospike/aerospike-client-go%2ev1.(*SyncMap).mappingExists(0x951f20, 0x0, 0x0, 0x0, 0x0)
/home/styles/Code/golang/src/gopkg.in/aerospike/aerospike-client-go.v1/marshal.go:172 +0x3f
gopkg.in/aerospike/aerospike-client-go%2ev1.cacheObjectTags(0x0, 0x0, 0x0)
/home/styles/Code/golang/src/gopkg.in/aerospike/aerospike-client-go.v1/marshal.go:199 +0x68
gopkg.in/aerospike/aerospike-client-go%2ev1.(*readCommand).parseObject(0xc8200146e0, 0x4, 0x0, 0x1, 0x278bbe, 0x0, 0x0)
/home/styles/Code/golang/src/gopkg.in/aerospike/aerospike-client-go.v1/read_command.go:194 +0x214
This looks like a bug. I'll fix it in the next release during this week.
Thank you, is there any work around I can do right now?
I also noticed type Service int if I use Service (which is actually an int), that isn't supported. Any chance that would be?
This bug is likely the time.Time that is giving you the error, since the field doesn't exist in the database. The type aliases are supported, as tested in the client_object_test.go
I removed the time and the service, same error. I only have two strings in a structure.
+-------+---------------+-------+-----------+ | quota | bin | count | namespace | +-------+---------------+-------+-----------+ | 32768 | "IPAddress" | 5 | "xxxx" | | 32768 | "service" | 5 | "xxxx" | | 32768 | "Service" | 5 | "xxxx" | | 32768 | "ipaddress" | 5 | "xxxx" | | 32768 | "reverse_dns" | 5 | "xxxx" | +-------+---------------+-------+-----------+
This is what's generated, I think that's an error and might be the cause? It's not saving it right into bins. I tried it with the annotations and without. I've been deleting the dat file to retest, same thing.
Can you test this with an memory-only database? Restarting the asd will wipe it clean, so you will make sure there is no residual data in the DB.
EDIT: Are you passing the ipAddr
in err = c.client.PutObject(nil, key, ipAddr)
as nil?
Yeah I shutdown the db and removed the dat file then restarted and saw no data in the namespace.
I'll make another test but I'm pretty sure that ip is never nil.
I'll test with in memory and ill see if u can create a simple test to reproduce it.
package main
import (
"time"
"github.com/aerospike/aerospike-client-go"
)
const (
namespace = "test"
set = "ips"
)
type aeroRepo struct {
client *aerospike.Client
qp *aerospike.QueryPolicy
}
func NewAeroRepo(c *aerospike.Client) aeroRepo {
return aeroRepo{
client: c,
qp: aerospike.NewQueryPolicy(),
}
}
func (c aeroRepo) Get(addr string) (ipAddr *IPAddress, err error) {
var key *aerospike.Key
key, err = aerospike.NewKey(namespace, set, addr)
if err != nil {
return
}
err = c.client.GetObject(nil, key, ipAddr)
return
}
func (c aeroRepo) Save(ipAddr *IPAddress) (err error) {
var key *aerospike.Key
key, err = aerospike.NewKey(namespace, set, ipAddr.IPAddress)
if err != nil {
return
}
err = c.client.PutObject(nil, key, ipAddr)
return
}
type IPAddress struct {
IPAddress string `as:"ipaddress"`
ReverseDNS string `as:"rdns"`
Service int `as:"service"`
Created time.Time `as:"created"`
}
func main() {
client, err := aerospike.NewClient("127.0.0.1", 3000)
if err != nil {
panic(err)
}
repo := NewAeroRepo(client)
ip := IPAddress{
IPAddress: "192.168.2.1",
ReverseDNS: "blah.arpa",
Service: 3,
Created: time.Now(),
}
if err := repo.Save(&ip); err != nil {
panic(err)
}
repo.Get("192.168.2.1")
}
This will reproduce it. Modify the namespace const and the connection string (default 127.0.0.1)
Thanks for the snippet. As I suspected, you're not allocating the *ipAddr
. Change your Get
method to this:
func (c aeroRepo) Get(addr string) (ipAddr *IPAddress, err error) {
var key *aerospike.Key
key, err = aerospike.NewKey(namespace, set, addr)
if err != nil {
return
}
// the following line is what makes the difference
ipAddr = &IPAddress{}
err = c.client.GetObject(nil, key, ipAddr)
return
}```
Weird, I've used that pattern before. ipAddr was supposed to be instantiated by the language. I'll do this as a work around though. Thank you!
As an improvement, I'll do it inside the library to make it easier.
Can you take a struct, have it save into columns based on annotations
as:"test"
and then query over them? I haven't seen any examples. I've only seen the EncodeBlob interface.