0

I have such a model in Django:

class Event(models.Model):                                                                                                 
    EVENT_TYPE_CHOICES = [(e, e.value) for e in EVENT_TYPE]                                                                
    event_type = models.TextField(choices=EVENT_TYPE_CHOICES)                                                              
                                                                                                                           
    date_of_event = models.DateTimeField(default=timezone.now, db_index=True)                                              
    event_data = JSONField()

And there is the event_data JSONField there which has the following structure:

    'project_id': project_id,                                                                                       
    'family_id': family_id,                                                                                         
    'variant_data': variant_data_list,                                                                              
    'username': user.username,                                                                                      
    'email': user.email, 

Where variant_data_list is a list of such dict objects with 3 str values:

{'xpos': xpos, 'ref': ref, 'alt': alt}

Now, I need a way to find unique Event model object based on the supplied variant_data_list (each object inside of it should be found within a single Events' variant_data_list, is it possible to achieve somehow? The number of items in variant_data_list is from 1 to 3.

Otherwise I am thinking of generating unique ids based on the variant_data_list each time it is written to postgres (but not sure how to make it either). Any suggestions would be greatly appreciated.

Nikita Vlasenko
  • 4,004
  • 7
  • 47
  • 87

1 Answers1

1

You may be able to filter on json fields as illustrated in this answer (Django JSONField filtering) - the following is untested:

# filter for events with a specific variant_data list:
Event.objects.filter(event_data__variant_data=[<the list>])

# filter for events with specific items in the variant data list:
Event.objects.filter(
    event_data__variant_data__contains='item1', 
    event_data__variant_data__contains='item2',
    ...
)

You can get a list of objects by looping over all your events which is likely less efficient:

events = [
    event for event in Event.objects.all() if event.event_data['variant_data'] == [<the list>]
]

You can also override your save method on events to as you suggested:

class Event(...):

    variant_data_id = models.CharField(...)
  
    ...
   
    def save(self, *args, **kwargs):

        self.variant_data_id = some_hash_method(self.event_data['variant_list']

        super(Event, self).save(*args, **kwargs)
Daniel
  • 3,228
  • 1
  • 7
  • 23
  • I don't know how to implement it with hash correctly, so that the collision would never happen. The first method may not work because the order of the objects in the list can be different, but the order should not matter. – Nikita Vlasenko Nov 06 '20 at 15:39
  • 1
    Well the variant_data_id field itself doesn't need to be unique, but maybe you want it to... You can change your query to account for the ordering of the items in the list by using `contains` - see the edit. – Daniel Nov 06 '20 at 15:54