我正在制作一个应用程序,将使用逻辑和模型搜索类似的药物,如果某种药物属于某一类特定类别,那么其他药物只有那些类别才会返回这些药物。 这是相关的代码和虚拟数据 -
views.py
class GetSimilarDrugs(APIView):
def get(self, request, format=None):
#import pdb
#pdb.set_trace()
get_req = request.GET.get('drugid', '')
simi_list = []
comp_class = DrugBankDrugEPClass.objects.filter(drug_bank_id = get_req).values_list('epc_id', flat=True).distinct()
for drg_id in DrugBankDrugEPClass.objects.values_list('drug_bank_id', flat = True).distinct():
classtocomp = DrugBankDrugEPClass.objects.filter(drug_bank_id = str(drg_id)).values_list('epc_id', flat=True).distinct()
complist = list(comp_class)
tolist = list(classtocomp)
if complist == tolist:
simi_list.append(drg_id)
return Response({'result':simi_list})
models.py
class DrugBankDrugEPClass(models.Model):
drug_bank = models.ForeignKey(DrugBankDrugs, on_delete=models.CASCADE)
epc = models.ForeignKey(DrugBankEPClass, on_delete=models.CASCADE)
虚拟SQL数据
id | drug_bank_id | epc_id |
+------+--------------+--------+
| 1 | DB12789 | 1 |
| 2 | DB12788 | 2 |
| 3 | DB00596 | 3 |
| 4 | DB09161 | 4 |
| 5 | DB01178 | 5 |
| 6 | DB01177 | 6 |
| 7 | DB01177 | 6 |
| 8 | DB01174 | 7 |
| 9 | DB01175 | 8 |
| 10 | DB01172 | 9 |
| 11 | DB01173 | 10 |
| 12 | DB12257 | 11 |
| 13 | DB08167 | 12 |
| 14 | DB01551 | 13 |
| 15 | DB01006 | 14 |
| 16 | DB01007 | 15 |
| 17 | DB01007 | 16 |
| 18 | DB01004 | 17 |
| 19 | DB01004 | 18 |
| 20 | DB01004 | 17 |
| 21 | DB01004 | 18 |
| 22 | DB01004 | 19 |
| 23 | DB00570 | 20 |
| 24 | DB01008 | 21 |
| 25 | DB00572 | 22 |
| 26 | DB00575 | 7 |
| 27 | DB00577 | 23 |
| 28 | DB00577 | 24 |
| 29 | DB00577 | 25 |
| 30 | DB00576 | 26 |
| 31 | DB00751 | 27 |
| 32 | DB00751 | 28 |
| 33 | DB00750 | 29 |
| 34 | DB00753 | 30 |
| 35 | DB00752 | 31 |
| 36 | DB00755 | 32 |
| 37 | DB00755 | 32 |
| 38 | DB00757 | 33 |
| 39 | DB00756 | 34 |
| 40 | DB00759 | 35 |
| 41 | DB00759 | 36 |
| 42 | DB00759 | 36 |
我得到了结果,但问题是它每次都在列表中进行迭代,因此花费了很多时间并且对于大量数据来说它确实很慢。还有其他方法可以更快地运作吗?
答案 0 :(得分:1)
根据您的需要,我认为您可以这样做:
get_req = request.GET.get('drugid', '')
# Fetching all the epc_ids that belongs to requisted drug_bank_ids
comp_class = DrugBankDrugEPClass.objects.filter(drug_bank_id = get_req).values_list('epc_id', flat=True).distinct()
# filters all drug_bank_ids thats matcth with the epc_ids in requisted
classtocomp = DrugBankDrugEPClass.objects.filter(epc_id__in = comp_class).values_list('drug_bank_id', flat=True).distinct()
UPD:
get_req = request.GET.get('drugid', '')
comp_class = DrugBankDrugEPClass.objects.filter(
drug_bank_id=get_req).values_list('epc_id', flat=True).distinct()
class_to_comp = DrugBankDrugEPClass.objects.filter(
epc_id__in=comp_class).values_list('drug_bank_id', 'epc_id')
d = {}
for k, v in class_to_comp:
d.setdefault(k, []).append(v)
simi_list = [k for k, v in d.items() if v == list(comp_class)]
print(simi_list)
我认为它会比你的代码快一点,因为如果我也在循环 就像你做的那样,它并没有在每个循环中击中数据库。它还可以循环过滤数据。
答案 1 :(得分:0)
您可以从
更改循环for drg_id in DrugBankDrugEPClass.objects.values_list('drug_bank_id', flat = True).distinct():
classtocomp = DrugBankDrugEPClass.objects.filter(drug_bank_id = str(drg_id)).values_list('epc_id', flat=True).distinct()
到
drug_ids = DrugBankDrugEPClass.objects.values_list('drug_bank_id', flat = True).distinct()
comps = DrugBankDrugEPClass.objects.filter(drug_bank_id__in = drug_ids).values_list('epc_id', flat=True).distinct()
然后遍历comps
结果集。
您应该执行的其他优化是将db_index = True
添加到您要查询的必要字段中。
如果您正在使用Postgres,则可以向distinct
添加字段参数:
仅在PostgreSQL上,您可以传递位置参数(* fields)以指定DISTINCT应应用的字段的名称。这转换为SELECT DISTINCT ON SQL查询。这是区别。对于正常的distinct()调用,数据库在确定哪些行是不同的时比较每行中的每个字段。对于具有指定字段名称的distinct()调用,数据库将仅比较指定的字段名称。
您可以在其中执行以下操作:
comps = DrugBankDrugEPClass.objects.values_list('drug_bank_id', flat = True).distinct('drug_bank_id', 'epc_id')
编辑添加:
此外,您可以使用django-silk
或django-debug-toolbar
等插件来分析您的查询和应用