1

I am fairly new in this realm and any help is appreciated

I have a table in Dynamodb database named Tenant as below: "TenantId" is the hash primary key and I have no other keys. And I have a field named "IsDeleted" which is boolean

Table Structure

I am trying to run a query to get the record with specified "TenantId" while it is not deleted ("IsDeleted == 0")

I can get a correct result by running the following code: (returns 0 item)

       var filter = new QueryFilter("TenantId", QueryOperator.Equal, "2235ed82-41ec-42b2-bd1c-d94fba2cf9cc");
        filter.AddCondition("IsDeleted", QueryOperator.Equal, 0);

        var dbTenant = await
            _genericRepository.FromQueryAsync(new QueryOperationConfig
            {
                Filter = filter
            }).GetRemainingAsync();

But no luck when I try to get it with following code snippet (It returns the item which is also deleted) (returns 1 item)

 var queryFilter = new List<ScanCondition>();
        var scanCondition = new ScanCondition("IsDeleted", ScanOperator.Equal, new object[]{0});
        queryFilter.Add(scanCondition);


        var dbTenant2 = await
            _genericRepository.LoadAsync("2235ed82-41ec-42b2-bd1c-d94fba2cf9cc", new DynamoDBOperationConfig
            {
             QueryFilter   = queryFilter,
             ConditionalOperator = ConditionalOperatorValues.And
            });

Any Idea why ScanCondition has no effect?

Later I also tried this: (throw exception)

            var dbTenant2 = await
            _genericRepository.QueryAsync("2235ed82-41ec-42b2-bd1c-d94fba2cf9cc", new DynamoDBOperationConfig()
            {
                QueryFilter = new List<ScanCondition>()
                {
                    new ScanCondition("IsDeleted", ScanOperator.Equal, 0)
                }
            }).GetRemainingAsync();

It throws with: "Message": "Must have one range key or a GSI index defined for the table Tenants"

Why does it complain about Range key or Index? I'm calling

public AsyncSearch<T> QueryAsync<T>(object hashKeyValue, DynamoDBOperationConfig operationConfig = null);

1 Answer 1

4

You simply cant query a table only giving a single primary key (only hash key). Because there is one and only one item for that primary key. The result of the Query would be that still that single item, which is actually Load operation not Query. You can only query if you have composite primary key in this case (Hash (TenantID) and Range Key) or GSI (which doesn't impose key uniqueness therefore accepts duplicate keys on index).

The second code attempts to filter the Load. DynamoDBOperationConfig's QueryFilter has a description ...

    // Summary:
    //     Query filter for the Query operation operation. Evaluates the query results and
    //     returns only the matching values. If you specify more than one condition, then
    //     by default all of the conditions must evaluate to true. To match only some conditions,
    //     set ConditionalOperator to Or. Note: Conditions must be against non-key properties.

So works only with Query operations

Edit: So after reading your comments on this...

I dont think there conditional expressions are for read operations. AWS documents indicates they are for put or update operations. However, not being entirely sure on this since I never needed to do a conditional Load. There is no such thing like CheckIfExists functionality as well in general. You have to read the item and see if it exists. Conditional load will still consume read throughput so your only advantage would be only NOT retrieving it in other words saving the bandwith (which is very negligible for single item).

My suggestion is read it and filter it in your application layer. Dont query for it. However what you can also do is if you very need it you can use TenantId as hashkey and isDeleted for range key. If you do so, you always have to query when you wanna get a tenant. With the query you can set rangeKey(isDeleted) to 0 or 1. This isnt how I would do it. As I said, would just read it and filter it at my application.

Another suggestion thing could be setting a GSI on isDeleted field and writing null when it is 0. This way you can only see that attribute in your table when its only 1. GSI on such attribute is called sparse index. Later if you need to get all the tenants that are deleted (isDeleted=1) you can simply scan that entire index without conditions. When you are writing null when its 0 dynamoDB wont put it in the index at the first place.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for the clarification. Could you confirm that the way I did this in the first code snippet is the correct way (or the best practice) for what I try to achieve? or there is a better way that I can achieve the same goal? Second, is there anywhere I can refer to for sample or proper documentation for the SDK?
Anyways to filter LoadAsync or Load then?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.