0

I'm using Django with Postgres.

On a page I can show a list of featured items, let's say 10.

  1. If in the database I have more featured items than 10, I want to get them random/(better rotate).

  2. If the number of featured item is lower than 10, get all featured item and add to the list until 10 non-featured items.

Because the random takes more time on database, I do the sampling in python:

count = Item.objects.filter(is_featured=True).count()

        if count >= 10:
            item = random.sample(list(Item.objects.filter(is_featured=True))[:10])
        else:
            item = list(Item.objects.all()[:10])

The code above miss the case where there less than 10 featured(for example 8, to add 2 non-featured).

I can try to add a new query, but I don't know if this is an efficient retrive, using 4-5 queries for this.

S-Man
  • 22,521
  • 7
  • 40
  • 63
user3541631
  • 3,686
  • 8
  • 48
  • 115
  • You can use `Item.objects.order_by('?').[:10]` for random objects in Queryset – ruddra Nov 03 '18 at 08:56
  • @ruddra, I know but using random in database on big number of records reduce a lot the database speed; besides my problem is not random, but retrieve others besides is_featured if is the case – user3541631 Nov 03 '18 at 09:01

2 Answers2

1

The best solution I could find is this:

 from itertools import chain
 items = list(chain(Item.objects.filter(is_featured=True).order_by('?'), Item.objects.filter(is_featured=False).order_by('?')))[:10]

In this way, the order of the querysets are retained, but downside is that items becomes a list not a Queryset. You can see more details in this SO Answer. FYI: there are some fantastic solutions like using Q or pipe but they don't retain order of queryset.

ruddra
  • 50,746
  • 7
  • 78
  • 101
1

SQL method: You can achieve that with an SQL statement like this:

SELECT      uuid_generate_v4(), *
FROM        table_name
ORDER BY    NOT is_featured, uuid_generate_v4()
LIMIT 10;

Explain: The generated UUID should simulate randomness (for the purpose of e-commerce, this should suffice). While sorting the rows by NOT is_featured will put the is_featured rows on top; and automatically flow the rows down to 10 limits if it run out of featured items.

jlee88my
  • 2,935
  • 21
  • 28
  • on a query with joins doesn't seems to work, but the problem is that the query from around 30ms, go to over 600ms after I add uuid_generate_v4() – user3541631 Nov 04 '18 at 09:49