2017-01-03 75 views
1

我有一個包含對象id及其各自排序分數的redis排序集。我需要檢索這些對象的Django查詢集,按照排序後的集合的分數排序。什麼是最有效的方式來做到這一點?我的數據庫是postgresql。檢索按照redis排序集排序的Django查詢集的性能最高的方法


目前,我檢索Redis的有序set和無序查詢集分開。接下來,我按照python中的排序集合的分數排序查詢集。可以在這裏切出有意義的步驟,例如以某種方式在檢索點排序查詢集等?

obj_ids_with_scr = get_ids_w_scr() #retrieves redis sorted set with scores 
    obj_ids = map(itemgetter(0),obj_ids_with_scr) # filters sorted set for just the obj ids 
    queryset = Widget.objects.filter(id__in=obj_ids) #unsorted queryset 
    a = dict(obj_ids_with_scr) #turning the sorted set into a dictionary 
    for obj_pk, sort_score in a: 
     obj = queryset.get(id=obj_pk) #get object with id equalling obj_pk 
     sort_score = obj #assign the object to the 'score' value of this key-value 
    result = a.values() #making a list of all values, that are now in sorted order 
    return result 
+0

你正在使用什麼數據庫? – 2ps

+0

我正在使用postgresql 9.3 –

回答

1

如果您使用的是Postgres,你可以模擬MySQL的order by field語法是通過定義自己field function in postgres討論here

CREATE FUNCTION field(anyelement, VARIADIC anyarray) RETURNS numeric AS $$ 
    SELECT 
    COALESCE(
    (SELECT i FROM generate_subscripts($2, 1) gs(i) 
     WHERE $2[i] = $1), 
    0); 
$$ LANGUAGE SQL STABLE 

然後用類似呼籲:

queryset = queryset.extra(
    select={'manual': "FIELD(id, %s)" % (','.join(map(str, obj_ids)),) }, 
    order_by=['manual'] 
) 

nb您還可以優化您的Python代碼像這樣,如果你選擇:

widgets = Widgets.objects.in_bulk(obj_ids) 
sorted_widgets = [ widgets[x] for x in obj_ids if x in widgets ] 

在散裝返回dict映射idWidget情況下,這是排序你正在做的類型有用。你可以閱讀更多關於它here

+0

感謝您的支持。第一種方法非常獨特 - 我將嘗試一下。第二個更簡單,但是'in_bulk'是什麼?它是否像'filter()'? –

+1

'in_bulk'就像過濾器一樣,你可以將它傳遞給一個ID列表,它將檢索具有這些ID的Widget。它也是特殊的,它返回一個將'id'映射到'Widget'的'dict'。 'Widgets.objects.filter(id__in = obj_ids)}中用於x的{x.id:x的簡寫形式}'。 – 2ps

+0

很酷。 'select_related'與'in_bulk'一起工作嗎? –