-1

There are some answers in some forums about this question where people are generally repeating the already confusing AWS documentation about DynamoDB, but I need an example to see how it actually works. I have this query :

SELECT id, message, created, FROM "messages"."sender_company_id-index" 
WHERE sender_company_id = 435634652 AND receiver_company_id = 69992528 
AND sender_user_id = 186 AND receiver_user_id = 201
ORDER BY id DESC

and it fails with this error message:

An error occurred during the execution of the command. ValidationException: Variable reference id in ORDER BY clause must be part of the primary key

created field is already indexed so what's wrong? Why does it require it to be "part of the primary key"? I would like to order by different fields in different cases so I cant have all of them set as primary key. I dont get it!

EDIT

I noticed some of the comments below state that ORDER BY is not a possibility using PartiQL. Also this SO link claims that. However, AWS official documentation states the opposite.

UPDATE:

I was able to make it work though not completely.

SELECT id, created, sender_company_id, receiver_company_id
       sender_user_name, sender_user_id, sender_company_name, receiver_company_name
       FROM "messages"."sender_company_id-created-index" 
       WHERE (sender_company_id = 435634652 OR receiver_company_id= 435634652)
       AND (sender_user_id = 186 OR receiver_user_id = 186) 
       ORDER BY created ASC, sender_company_id ASC

Error:

ValidationException: Must have at least one non-optional hash key condition in WHERE clause when using ORDER BY clause.

If I change the WHERE to this it works:

...WHERE sender_company_id = 435634652

Here is my indexes:

Screenshot of indexes in AWS

It is beyond my understanding what's going on here. I do have the indexes, I am using non-optional (key partitions) in the WHERE clause but it fails.

showtime
  • 1
  • 1
  • 17
  • 48
  • 2
    DynamoDB supports a subset of PartiQL features. It is not, and does not claim to be, fully-featured SQL support, able to execute arbitrary SQL queries. It is gated by the underlying features of DynamoDB (such as query/scan and item ordering). You cannot ORDER BY arbitrary attributes, as you've seen. You cannot ORDER BY without also having a valid WHERE clause, for example. – jarmod Jun 02 '22 at 15:44
  • 1
    Upon further testing - i was able to duplicate this issue. I am checking with the team – smac2020 Jun 02 '22 at 15:48
  • 1
    I checked with the team and this is intended functionality. They will be making a doc update too – smac2020 Jun 02 '22 at 16:31
  • What is the Partition Key and Sort Key of the `sender_company_id-index` index? – fedonev Jun 02 '22 at 17:01
  • @fedonev a partition key of sender_company_id-index ? How can you even make a partition key for an index? I already set the partition key when created the table, and it is "id" – showtime Jun 03 '22 at 07:03
  • @smac2020 Is there any way to accomplish ORDER BY using PartiQL? – showtime Jun 03 '22 at 07:04
  • @jarmod So, there is no way to ORDER BY using partiql? – showtime Jun 03 '22 at 07:04
  • When you create a GSI, you provide a partition key and an optional sort key, just like when you created the base table. A GSI is an index with a different partition key than the one on the base table. A GSI can have a simple or composite primary key. Think of a GSI as another table, if you like, that has a different partitioning scheme. – jarmod Jun 03 '22 at 10:56
  • @jarmod when you create a GSI, that partition key is it a field of the table right? – showtime Jun 03 '22 at 11:03
  • It can be any attribute you like, even one that doesn't currently appear in any item of the table. All items that contain a matching attribute will be indexed in the GSI. – jarmod Jun 03 '22 at 11:16
  • @jarmod can you take a look at the example posted below by fedonev where he is creating a GSI with a partition key that doesnt exist GSI1PK and a sort key that doesnt exists GSI1SK and then he ORDERS BY Sort key (SK) ? – showtime Jun 03 '22 at 11:22
  • Not sure what you mean by "he is creating a GSI with a partition key that doesnt exist GSI1PK". The partition key of the example GSI1 index is the attribute GSI1PK, and the sort key is the attribute GSI1SK. They *do* exist in the example item, though they are not part of the base table's composite index (and they don't have to be). – jarmod Jun 03 '22 at 12:56
  • BTW you didn't answer the earlier question from @fedonev about the pk/sk of the sender_company_id-index, but from the naming I am assuming that it has a pk of sender_company_id and it has no sk. – jarmod Jun 03 '22 at 13:08
  • @jarmod I mean how do you order by some field if that field does not exist in the table? That makes absolutely no sense to me. – showtime Jun 03 '22 at 13:28
  • @jarmod I made a working example, please check the update. I have another problem now. – showtime Jun 03 '22 at 13:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/245298/discussion-between-jarmod-and-showtime). – jarmod Jun 03 '22 at 13:40

1 Answers1

2
[EDIT: OP added index key details and a second PartiQL statement]

Error #1 is happening because you can only ORDER BY a field that is the sender_company_id-index index's Partition (=Hash) Key or Sort (=Range) Key*. See the first block of unhappy examples marked ❌. Error #2 is happening because ORDER BY seems to be supported only for query operations (your second statement is a scan). This constraint makes sense, but I could not find it documented anywhere. See the second block of unhappy ❌ examples. But first, some working ORDER BY examples:

I need an example to see how it actually works.

my-table has a Partition Key PK and Sort Key SK. The table has one secondary index, named GSI1. The index uses the GSI1PK field as its Partition Key and its Sort Key is GSI1SK. Here's a sample record:

{
 "PK": "1x", "SK": "cc", "GSI1PK": "a", "GSI1SK": "b1", "Other": "foo", "Another": "bar"
}

These are valid PartiQL ORDER BY statements:

SELECT * FROM "my-table"        WHERE PK = '1x'                              ORDER BY SK     ASC
SELECT * FROM "my-table"."GSI1" WHERE GSI1PK = 'a'                           ORDER BY GSI1SK ASC
SELECT * FROM "my-table"."GSI1" WHERE GSI1PK IN ['a', 'b']                   ORDER BY GSI1PK DESC, GSI1SK ASC
SELECT * FROM "my-table"."GSI1" WHERE GSI1PK IN ['a', 'b']                   ORDER BY GSI1SK DESC, GSI1PK DESC
SELECT * FROM "my-table"."GSI1" WHERE GSI1PK IN ['a', 'b'] AND Other = 'foo' ORDER BY GSI1SK DESC, GSI1PK DESC

However, ordering by fields other than the Primary Keys of the index I'm querying on will fail:

-- ValidationException: Variable reference Other in ORDER BY clause must be part of the primary key
❌ SELECT * FROM "my-table"."GSI1" WHERE GSI1PK = 'a' ORDER BY Other ASC
-- ValidationException: Variable reference GSI1PK in ORDER BY clause must be part of the primary key
❌ SELECT * FROM "my-table" WHERE PK = 'a' ORDER BY GSI1PK ASC

ORDER BY apparently also requires a WHERE clause with a = or IN condition on the Partition Key. That is, ordering succeeds for query operations. Scan operations with ordering fail:

-- ValidationException: Must have WHERE clause in the statement when using ORDER BY clause.
❌ SELECT * FROM "my-table" ORDER BY SK ASC

-- ValidationException: Must have at least one non-optional hash key condition in WHERE clause when using ORDER BY clause.
❌ SELECT * FROM "my-table" WHERE begins_with(PK, 'b') ORDER BY SK ASC

the created field is already indexed so what's wrong?

DynamoDB secondary indexes are fundamentally different than their RDBMS cousins. A secondary index lets you query the data in the table using an alternate key.

Why does it require it to be "part of the primary key"? I would like to order by different fieldds

DynamoDB imposes design constraints to preserve its scalability superpowers.


* You can only order by the primary key elements of your statement's table[.index], as in the docs: SELECT ... FROM table[.index] ORDER BY key [DESC|ASC], where key is a "hash key or a sort key to use to order returned results."

fedonev
  • 20,327
  • 2
  • 25
  • 34
  • ok, still confusing. In the first example you took, it seems like you can order by using primary key which in my case in "id". And I did try to order by using id field, it still shows the same error. – showtime Jun 03 '22 at 09:07
  • I got it now, I just added an index in one of the fields and a sort key to created field. I am now able to order by created unix timestamp. Thats all I needed to know. – showtime Jun 03 '22 at 09:35
  • I have a simple question, should I create indexes for all fields that I use in WHERE clauses? – showtime Jun 03 '22 at 10:16
  • When you say "...The table has one secondary index, named GSI1. The index has a Partition Key GSI1PK and Sort Key GSI1SK" what do you actually mean??? How can you actually create an index with partition key of a field that doesn't even exist GSI1PK ?! Shouldn't the partition key be PK and sort key SK and then name the index as you wish? Please explain – showtime Jun 03 '22 at 10:52
  • Read [General Guidelines for Secondary Indexes in DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-indexes-general.html). Becoming a DynamoDB Master is like becoming a Jedi Master. You must forget what you know about RDBMS and embrace [DynamoDB NoSQL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-general-nosql-design.html). As Yoda said to Luke: _"Always with you what cannot be done. Hear you nothing that I say?… You must unlearn what you have learned."_ Feel the Force, @showtime! – fedonev Jun 03 '22 at 10:53
  • thanks, i will go through them. I just believe the examples you took are actually wrong. – showtime Jun 03 '22 at 11:07
  • 1
    In terms of learning the intricacies of DynamoDB, read everything you can by [Alex DeBrie](https://github.com/alexdebrie/awesome-dynamodb). – jarmod Jun 03 '22 at 11:18
  • 1
    @showtime My examples use the DynamoDB [generic key name pattern](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-modeling-nosql-B.html). I ran all the examples in a live table. But if you find an error, let me know! – fedonev Jun 03 '22 at 11:21
  • @fedonev can you please take an example using the naming I provided in the query I posted? In the examples you took you are sorting by a sort key which is not in the index nor sort key. – showtime Jun 03 '22 at 11:24