How to get record bins before update when using operate

I’m trying to update multiple keys in a map and get the record values before it’s updated. I’m using the “operate” operation with an “op_get” to get the record and then a “put_items” operation but I get a “PARAMETER_ERROR (4)” when used together. This is the go code using ( aerospike-client-go v4.5.2:

key, err := aero.NewKey(r.namespace, r.set, id)
if err != nil {
	return util.Wrapf(err, "error creating key for fpid %s", id)
}

// Read op before any update
ops := []*aero.Operation{aero.GetOp()}
mapPolicy := aero.NewMapPolicy(aero.MapOrder.KEY_ORDERED, aero.MapWriteMode.UPDATE)

if len(itemsToAdd) > 0 {
	items := map[any]any{}
	for k, v := range itemsToAdd {
		items[k] = v
	}
	ops = append(ops, aero.MapPutItemsOp(mapPolicy, "items", items))
}

// Here I get the PARAMETER_ERROR when reading and writing in the same "operate"
record, err := r.client.Operate(r.writePolicy, key, ops...)

Is this an Aerospike limitation? Is there any way to read the old record value before updating it transactionally?

Thank you!

I am not a developer but the sandbox makes it so easy to try things out that I did the following and seem I am able to get the value of a bin before it gets updated and returned in a single shot.

I first used the sample on this page of the sandbox to create a new record:

import (
    "fmt"
    "github.com/aerospike/aerospike-client-go/v6" 
)

// Establishes a connection to the server
client, err := aerospike.NewClient("127.0.0.1", 3000)

// Creates a key with the namespace "sandbox", set "ufodata", and user key 5001
key, err := aerospike.NewKey("sandbox", "ufodata", 5001)

// Create posted bin to insert
posted := aerospike.NewBin("posted", 20220602)

// Update the record
record, err := client.Operate(nil, key, 
    aerospike.PutOp(posted),
    aerospike.MapPutOp(aerospike.DefaultMapPolicy(), "report", aerospike.NewValue("city"), aerospike.NewValue("Ypsilanti")),
    aerospike.GetBinOp("report"))
    
// Do something
fmt.Printf("Record: %v", record.Bins)

// Close the connection to the server
client.Close()

I then tried the following to basically update the bin “posted” but read its value prior to the update and got the expected value… running a second time then shows the updated value:

import (
    "fmt"
    "github.com/aerospike/aerospike-client-go/v6" 
)

// Establishes a connection to the server
client, err := aerospike.NewClient("127.0.0.1", 3000)

// Creates a key with the namespace "sandbox", set "ufodata", and user key 5001
key, err := aerospike.NewKey("sandbox", "ufodata", 5001)

// Create posted bin to insert
posted := aerospike.NewBin("posted", 20220603)

// Update the record
record, err := client.Operate(nil, key, 
    aerospike.GetBinOp("posted"),
    aerospike.PutOp(posted),
    aerospike.MapPutOp(aerospike.DefaultMapPolicy(), "report", aerospike.NewValue("city"), aerospike.NewValue("Ypsilanti")),
    aerospike.GetBinOp("report"))
    
// Do something
fmt.Printf("Record: %v", record.Bins)

// Close the connection to the server
client.Close()

But I don’t know whether this is the proper way to use the API. I am pretty sure this is supposed to work, including within CDTs, but curious if it doesn’t work for you somehow.

Hi @meher, thank you for your reply! First of all, thank you for introducing me to the sandbox, I didn’t know it, so helpful!

I see the problem now, I was using aero.GetOp() instead of aero.GetOpForBin("my_bin") which gets a single bin. As far as I understand from here I can’t get the entire record as an operation, only individual bins, not sure why aero.GetOp(), it doesn’t exist in the node.js library.

Thank you for your help!!

This topic was automatically closed 84 days after the last reply. New replies are no longer allowed.