Django performance with `not in` filter with giant

2019-08-17 23:04发布

I am currently making a school project where I am building a website that lets you rate nearby restaurants (1-5 stars). The only caveat is that I will show users the restaurants based on location (e.g. closest ones first) and that once they have rated a restaurant, it will never be shown to them again.

Currently I have something like this in mind

class User(models.Model):
    username = models.CharField(primary_key=True, max_length=20)
    location = models.SomeGeoPointField
    ...

class Restaurant(models.Model):
    title = models.CharField(primary_key=True, max_length=20)
    location = models.SomeGeoPointField
    ...

class Rating(models.Model):
    for    = models.ForeignKey(User, on_delete=models.CASCADE)
    from   = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
    rating = models.IntegerField()

I am having trouble thinking how the query would look like, and if I used a not in to filter out existing ratings, about the possible performance hit

1条回答
等我变得足够好
2楼-- · 2019-08-17 23:45

The query you need is one that excludes the restaurants which the user has already rated. Django will create an efficient query if you do this:

Restaurant.objects.exclude(rating__user=request.user)

You can make the queries even easier if you recognise that what you have here is a many-to-many relationship between User and Restaurant, with a through table of Rating. So:

class User(models.Model):
    ...
    ratings = models.ManyToManyField('Restaurant', through='Rating', related_name='users_rating')

This doesn't actually alter this query very much - now it is:

Restaurant.objects.exclude(users_rating=request.user)

but it will certainly make other queries easier.

查看更多
登录 后发表回答