2

I'm using Pynamodb for interacting with dynamodb. However, last_evaluated_key always returns null even if there are multiple items. When I run this query

results = RecruiterProfileModel.profile_index.query(
        hash_key=UserEnum.RECRUITER,
        scan_index_forward=False,
        limit=1,
    )

If I try getting this value

results.last_evaluated_key

it always returns null.

However, if I dump the results object, it returns

{
    "page_iter": {
        "_operation": {},
        "_args": [
            "recruiter"
        ],
        "_kwargs": {
            "range_key_condition": null,
            "filter_condition": null,
            "index_name": "PROFILE_INDEX",
            "exclusive_start_key": {
                "sk": {
                    "S": "PROFILE#6ab0f5bc-7283-4236-9e37-ea746901d19e"
                },
                "user_type": {
                    "S": "recruiter"
                },
                "created_at": {
                    "N": "1677398017.685749"
                },
                "pk": {
                    "S": "RECRUITER#6ab0f5bc-7283-4236-9e37-ea746901d19e"
                }
            },
            "consistent_read": false,
            "scan_index_forward": false,
            "limit": 1,
            "attributes_to_get": null
        },
        "_last_evaluated_key": {
            "sk": {
                "S": "PROFILE#95a4f201-2475-45a7-b096-5167f6a4d639"
            },
            "user_type": {
                "S": "recruiter"
            },
            "created_at": {
                "N": "1677398017.68518"
            },
            "pk": {
                "S": "RECRUITER#95a4f201-2475-45a7-b096-5167f6a4d639"
            }
        },
        "_is_last_page": false,
        "_total_scanned_count": 2,
        "_rate_limiter": null,
        "_settings": {
            "extra_headers": null
        }
    },
    "_map_fn": {},
    "_limit": 0,
    "_total_count": 1,
    "_index": 1,
    "_count": 1,
    "_items": [
        {
            "company_name": {
                "S": "fletcher-rodriguez"
            },
            "created_at": {
                "N": "1677398017.685749"
            },
            "last_name": {
                "S": "craig"
            },
            "first_name": {
                "S": "tyler"
            },
            "designation": {
                "S": "manager"
            },
            "verification_status": {
                "S": "pending"
            },
            "sk": {
                "S": "PROFILE#6ab0f5bc-7283-4236-9e37-ea746901d19e"
            },
            "user_type": {
                "S": "recruiter"
            },
            "email": {
                "S": "fowlerkathy@hernandez.com"
            },
            "pk": {
                "S": "RECRUITER#6ab0f5bc-7283-4236-9e37-ea746901d19e"
            }
        }
    ]
}

You can clearly see that last_evaluated_key exists over there. I'm getting confused here. Please help. I've deadlines to meet. Thank you in advance.

Edit: Here is a video attachment of trying to get the value of last_eveluated_key in different ways and they all return null pynamodb last_evaluated_key issue Gdrive video

Koushik Das
  • 9,678
  • 3
  • 51
  • 50
  • Why do you need `last_evaluated_key` with `limit: 1` and no `last_evaluated_key` in the query? Unless this example is not exactly what you're trying to do. – Destroy666 Feb 26 '23 at 08:59

2 Answers2

2

The result returned by the query() is the ResultIterator object, which is an iterator. Its last_evaluated_key is the key of the last item you pulled from the iterator, not DynamoDB. Because your code have not yet asked to retrieve any items, the last_evaluated_key is not set.

You need to process some or all of the items in the result:

for item in results:
    print(item)
return results.last_evaluated_key

then you will get the key of the last item you processed.

Alex Chadyuk
  • 1,421
  • 2
  • 10
1

I've never used Pynamo but the key to LastEvaluatedKey looks like _last_evaluated_key which is prefixed with _ have you tried that?

results._last_evaluated_key

Update based on question:

Pagination and last evaluated key

The query returns a ResultIterator object that transparently paginates through results. To stop iterating and allow the caller to continue later on, use the last_evaluated_key property of the iterator:

def iterate_over_page(last_evaluated_key = None):
    results = TestModel.view_index.query('foo', TestModel.view > 0,
                                         limit=10,
                                         last_evaluated_key=last_evaluated_key)
    for item in results:
       ...
    return results.last_evaluated_key

Ref

I believe your issue is that you haven't initiated the query when you're looking for the LastEvaluatedKey. Try print some items first, before trying to obtain the key.

Leeroy Hannigan
  • 11,409
  • 3
  • 14
  • 31
  • @lee-hannigan This will return in error – Koushik Das Feb 26 '23 at 13:14
  • Even that also returns `null`. Here is the video of me trying that [link of video of me trying that](https://drive.google.com/file/d/1LbImYQbx4Kz2gGQcFOa0Vz1bJJyhWPuw/view?usp=share_link) – Koushik Das Feb 26 '23 at 13:14
  • Updated my question based on your feedback. I've not used PynamoDB but their docs make it clear you get returned an iterator. Check my answer. – Leeroy Hannigan Feb 26 '23 at 15:23
  • @LeeHannigan from the manual you quoted, "The `last_evaluated_key` is effectively the key attributes of the last iterated item" meaning that the query has been completed and stored in the iterator. Please see my response. – Alex Chadyuk Feb 26 '23 at 15:51
  • HI, @LeeHannigan thank you very much for the effort. I really appreciate it. The solution by Alex worked actually. – Koushik Das Feb 26 '23 at 16:46
  • @LeeHannigan You're correct in your edit. I will leave an upvote. – Koushik Das Feb 26 '23 at 16:47
  • If the query had not been initiated, how could `results` possibly print the contents of the DynamoDB record, in your original question? The answer is misleading @KoushikDas – Alex Chadyuk Feb 26 '23 at 19:36