baopham / laravel-dynamodb

Eloquent syntax for DynamoDB
https://packagist.org/packages/baopham/dynamodb
MIT License
484 stars 128 forks source link

Unable to update data using where() #262

Closed Geet2312 closed 1 year ago

Geet2312 commented 1 year ago

I'm unable to update data using the eloquent model, this is how I implement

TestModel::where(['pk'=>'1','sk'=>'2']) ->update(['first_name'=>'Lai','last_name'=>'James']);

but if I add first() it updated and I'm not sure whether it is the best practice or not

TestModel::where(['pk'=>'1','sk'=>'2']) ->first() ->update(['first_name'=>'Lai','last_name'=>'James']);

zoe-edwards commented 1 year ago

The way DynamoDB works is that you can only update one item at a time, so an update all isn’t really possible. Hence this package does not support that type of query.

Geet2312 commented 1 year ago

Hi, I'm using a composite key, can you give me an example of how to update data using the model? I am asking this because I fail to update the data following the documentation.

zoe-edwards commented 1 year ago

Did you follow the instructions for Composite Keys?

You need

protected $primaryKey = 'customer_id';
protected $compositeKey = ['customer_id', 'agent_id'];

in your model, then you can use it like so:

$model->find(['customer_id' => 'value1', 'agent_id' => 'value2']);
Geet2312 commented 1 year ago

Yes, I did follow the instruction and this implementation $model->find(['customer_id' => 'value1', 'agent_id' => 'value2'])->update($attributes); works perfectly fine now. But this update is done by performing two operations, right?

  1. Scan operation to find the data
  2. UpdateItem operation to update the data Please, correct me if I'm wrong.
zoe-edwards commented 1 year ago

Yeah the nature of Laravel and Eloquent is that it’ll fetch anything that you find.

If you’re using the $compositeKey correctly, that will perform a Query, not a Scan.

If you want, you can directly use the DynamoDb facade – but it’s not something that fits in with the Eloquent way of working.

use BaoPham\DynamoDb\Facades\DynamoDb;

$key // string
$attribute // string
$value

DynamoDb::table('YourTable')
    ->setKey(DynamoDb::marshalItem(['id' => $key]))
    ->setUpdateExpression('SET #a = :v')
    ->setExpressionAttributeName('#a', $attribute)
    ->setExpressionAttributeValue(':v', DynamoDb::marshalValue($value))
    ->setReturnValues('ALL_NEW')
    ->prepare(DynamoDb::client('aws_connection'))
    ->updateItem();

And that will write without a read.

Geet2312 commented 1 year ago

Thank you @zoe-edwards for enlightening me. This facade implementation will do for me 👍.