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!!