2017-04-20 47 views
2

我有10萬個記錄在兩個模型「A」,並在模型「B」比較模型B的場的Django模型A的字段的值

例:

class A(models.Model): 
    user_email = models.EmailField(null=True, blank=True) 
    user_mobile = models.CharField(max_length=30, null=True, blank=True) 
    book_id = models.CharField(max_length=255, null=True, blank=True) 
    payment_gateway_response = JSONField(blank=True, null=True) 

class B(models.Model): 
    order = models.ForeignKey(A, null=True, blank=True) 
    pay_id = models.CharField(max_length=250, null=True, blank=True) 
    user_email = models.EmailField(null=True, blank=True) 
    user_mobile = models.CharField(max_length=30, null=True, blank=True) 
    created = models.DateTimeField(blank=True, null=True) 
    total_payment = models.DecimalField(decimal_places=3, max_digits=20, blank=True, null=True) 

我想用獲得B的對象A的值

例如

all_a = A.objects.all() 
for a in all_a: 
    b = B.objects.filter(user_email=a.user_email, user_mobile=a.user_mobile) 

這很好,我得到的結果。但是,因爲它是10萬條記錄,所以花費的時間太多了。循環迭代需要時間。 django有沒有更快的方法來做到這一點?

+0

你究竟在爲循環使用什麼?當你得到它時,你用'b'做什麼? – Sayse

+0

它只是用於比較交易。沒有更多 – Gaurav

回答

0

如果你不感興趣的緩存模型,您可以選擇使用iterator()的性能提升(見參考https://docs.djangoproject.com/en/1.11/ref/models/querysets/#iterator):

for a in A.objects.all().iterator(): 
    b = B.objects.filter(user_email=a.user_email, user_mobile=a.user_mobile) 
+0

這仍然是n + 1查詢,在OP的情況下是100K + 1。 – v1k45

+0

我需要對象a。需要用一些值更新它。 – Gaurav

0

你可以做

import operator 
from django.db.models import Q 

q = A.objects.all().values('user_email', 'user_mobile') 
B.objects.filter(reduce(operator.or_, [Q(**i) for i in q])) 

如果您想用b對象做一些操作,取決於a。這不是方法。

1

您可以使用這些值獲取a和b中的每個值的列表。

a = A.objects.all() 
emails = list(a.values_list('user_email', flat=True)) 
mobiles = list(a.values_list('user_mobile', flat=True)) 

b = B.objects.filter(user_email__in=emails, user_mobile__in=mobiles) 

如何過的結果可能有對電子郵件和移動未在A.對,但如果你確保電子郵件和手機將被一個獨特的,在B的電子郵件和移動的總部設在一個的A'模型,那麼你不會有任何問題。

+0

你的答案看起來不錯,但不適合我的情況。 – Gaurav