Adam
Adam

Reputation: 483

Redis: how to efficiently check for empty nested key

I have a nested dictionary in my redis store and need to find all records where key_2 == "" then return value in key_3. All key_3 values will then be used to run mysql query to get key_2 value and update the redis store.

[
  ...
  task_44903: {"key_1": 44903, "key_2": "", "key_3": 1}
  task_44229: {"key_1": 44229, "key_2": 4, "key_3": 2}
  ...
]

My current way of achieving this is

    keys = r.keys(pattern='task_*')
    key_3 = set()
    for key in keys:
        values = r.get(key).decode('utf-8')
        values = ast.literal_eval(values)
        if values['key_2'] == '':
            key_3.add(values['key_3'])   

Is there a more concise way of achieving this?

Upvotes: 0

Views: 246

Answers (2)

ComplicatedPhenomenon
ComplicatedPhenomenon

Reputation: 4189

I'm not sure if this is what you wanted.

data = [
  {'task_44903': {"key_1": 44903, "key_2": "", "key_3": 1}},
  {'task_44229': {"key_1": 44229, "key_2": "", "key_3": 1}},
  {'task_44230': {"key_1": 44229, "key_2": "", "key_3": 2}}
]

set([ v['key_3'] for item in data for _, v in item.items()  if v['key_2']==""])

Output

{1, 2}

Upvotes: 1

awakenedhaki
awakenedhaki

Reputation: 301

Modify this to fit with your pipeline.

from itertools import chain


tasks = [
  {'task_44903': {"key_1": 44903, "key_2": "", "key_3": 1}},
  {'task_44229': {"key_1": 44229, "key_2": 4, "key_3": 2}}
]


def check_empty_key(tasks):
    # Your desired return value
    key_3s = set()

    # Makes a list of [{key_1:..., key_2:...}, {key_1:..., key_2:...}]
    task_details = chain.from_iterable(task.values() for task in tasks)
    # Iterate through each of these dictionaries
    for task_detail in task_details:
        # Will evaluate to True if task_detail['key_2'] is an empty string
        if not task_detail['key_2']:
            # Adds to the key_3s set
            key_3s.add(task_detail['key_3'])
            break
    else:
        # If no break statement was hit in the for loop, then raise this error
        raise ValueError('No empty key_2 in tasks')
    return key_3s

You could also do it like this:

def check_empty_key(tasks):
    key_3s = set()
    task_details = chain.from_iterable(task.values() for task in tasks)
    for task_detail in task_details:
        if not task_detail['key_2']:
            key_3s.add(task_detail['key_3'])
    return key_3s

But I like having the else so that I can raise an error when I need to add that into my control flow.

Upvotes: 0

Related Questions