Muhammad Younas
Muhammad Younas

Reputation: 1601

Illegal query expression: No hash key condition is found in the query in AWS Query

I have table in AWS mobile hub and I am using the following model for it

public class UserstopcoreDO {
    private String _userId;
    private String _usertoplevel;
    private String _usertopscore;
    private String _username;

    @DynamoDBHashKey(attributeName = "userId")
    @DynamoDBAttribute(attributeName = "userId")
    public String getUserId() {
        return _userId;
    }

    public void setUserId(final String _userId) {
        this._userId = _userId;
    }

    @DynamoDBAttribute(attributeName = "usertoplevel")
    public String getUsertoplevel() {
        return _usertoplevel;
    }

    @DynamoDBAttribute(attributeName = "username")
    public String getUsername() {
        return _username;
    }

    public void setUsername(final String _username) {
        this._username = _username;
    }

    public void setUsertoplevel(final String _usertoplevel) {
        this._usertoplevel = _usertoplevel;
    }

    @DynamoDBIndexHashKey(attributeName = "usertopscore", globalSecondaryIndexName = "usertopscore")
    public String getUsertopscore() {
        return _usertopscore;
    }

    public void setUsertopscore(final String _usertopscore) {
        this._usertopscore = _usertopscore;
    }

}

In the table, I have 1500+ records and now I want to fetch Top 10 records from it so for that I write the below query

final DynamoDBQueryExpression<UserstopcoreDO> queryExpression = new DynamoDBQueryExpression<>();
            queryExpression.withLimit(10);
            queryExpression.setScanIndexForward(false);
            final PaginatedQueryList<UserstopcoreDO> results = mapper.query(UserstopcoreDO.class, queryExpression);
            Iterator<UserstopcoreDO> resultsIterator = results.iterator();
            if (resultsIterator.hasNext()) {
                final UserstopcoreDO item = resultsIterator.next();
                try {
                    Log.d("Item :",item.getUsertopscore());
                } catch (final AmazonClientException ex) {
                    Log.e(LOG_TAG, "Failed deleting item : " + ex.getMessage(), ex);
                }
            }

But when I run the code it gives me an error

Caused by: java.lang.IllegalArgumentException: Illegal query expression: No hash key condition is found in the query

but in my condition, I did not need any condition because I want to fetch top 10 records instead of one specific record. So how to handle that condition ?

Upvotes: 4

Views: 13487

Answers (2)

Sarah Messer
Sarah Messer

Reputation: 4083

If you want to "query" DynamoDB without specifying all HashKeys, use a Scan instead, i.e. DynamoDBScanExpression. You probably also want to change your "usertopscore" to be a RangeKey instead of a HashKey.

From https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBQueryExpression.html every DynamoDBQueryExpression requires all the Hash Keys be set.

Also see boto dynamodb2: Can I query a table using range key only?

Upvotes: 6

notionquest
notionquest

Reputation: 39226

Please set the hash key in the query expression. Below is the example of query expression for main table and GSI (need to set the index name).

Querying the main table:-

Set the hash key value of the table.

UserstopcoreDO hashKeyObject = new UserstopcoreDO();
hashKeyObject.setUserId("1");

DynamoDBQueryExpression<UserstopcoreDO> queryExpressionForMainTable = new DynamoDBQueryExpression<UserstopcoreDO>()
    .withHashKeyValues(hashKeyObject);

Querying the Index:-

Set the index name and hash key value of the index.

UserstopcoreDO hashIndexKeyObject = new UserstopcoreDO();
    hashIndexKeyObject.setUsertoplevel("100");

DynamoDBQueryExpression<UserstopcoreDO> queryExpressionForGsi = new DynamoDBQueryExpression<UserstopcoreDO>()
            .withHashKeyValues(hashIndexKeyObject).withIndexName("usertopscore");

GSI attributes in mapper:-

@DynamoDBIndexHashKey(attributeName = "usertoplevel",  globalSecondaryIndexName = "usertopscore")
public String getUsertoplevel() {
    return _usertoplevel;
}

@DynamoDBIndexRangeKey(attributeName = "usertopscore", globalSecondaryIndexName = "usertopscore")
public String getUsertopscore() {
    return _usertopscore;
}

Upvotes: 5

Related Questions