class QueryExpression {

    public DynamoDBQueryExpression<T> forQuery()
    {
        if(primaryKeyQueries.size() == 0)
        {
            logger.warn("No queries found with primary key field.");
            return null;
        }

        Map<String, AttributeValue> awsQueryValueMap = new HashMap<>();
        DynamoDBQueryExpression<T> expression = new DynamoDBQueryExpression<>();

        // add in the primary key queries (may optionally include the sort key)
        expression.withKeyConditionExpression(String.join(AND_STATEMENT, generateConditions(primaryKeyQueries, awsQueryValueMap)))
            .withExpressionAttributeValues(awsQueryValueMap)
            .withConsistentRead(false);

        if(filterAttributes != null)
        {
            expression.withProjectionExpression(filterAttributes);
        }
        if(queryIndex != null)
        {
            expression.withIndexName(queryIndex.getName());
        }
        if(filterQueries != null && filterQueries.size() > 0)
        {
            expression.withFilterExpression(String.join(AND_STATEMENT, generateConditions(filterQueries, awsQueryValueMap)));
        }
        /* // item limits are meaningless to DynamoDB expressions (at least in the current context)
        if (limitQuery != null){}
        */
        if(selectQuery != null)
        {
            expression.withSelect(selectQuery);
        }

        logger.info("DynamoDB query with key condition={}, value map={}, limit={}, fields={}", expression.getKeyConditionExpression(), awsQueryValueMap.toString(),
            expression.getLimit(), expression.getProjectionExpression());

        return expression;
    }

    public  QueryExpression(TableIndexes tableIndexes, List<Query> queries);

}