使用Django查询降低SQL数据库中的搜索成本

2024-10-02 08:28:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在制作一个应用程序,将搜索类似的药物使用的逻辑和模型,如果一种药物是在一个特定的类,然后其他药物,在这些只有那些类,然后它会返回这些药物。 以下是相关代码和虚拟数据-

视图.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})

型号.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 |

我得到的结果,但问题是,它迭代通过列表每次,从而采取了非常多的时间和大量的数据,它是真的很慢。有没有别的办法让它工作得更快?你知道吗


Tags: 数据idgetobjectsmodelslistclassbank
2条回答

根据您的需要,我认为您可以这样做:

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()

升级版:

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)

我认为它会比你的代码快一点,因为如果我也循环 就像你做的那样,它不会在每个循环中命中数据库。它还可以循环过滤数据。你知道吗

你可以从

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,可以将字段参数添加到^{}

On PostgreSQL only, you can pass positional arguments (*fields) in order to specify the names of fields to which the DISTINCT should apply. This translates to a SELECT DISTINCT ON SQL query. Here’s the difference. For a normal distinct() call, the database compares each field in each row when determining which rows are distinct. For a distinct() call with specified field names, the database will only compare the specified field names.

您可以在其中执行以下操作:

comps = DrugBankDrugEPClass.objects.values_list('drug_bank_id', flat = True).distinct('drug_bank_id', 'epc_id')

编辑以添加:

此外,您可以使用^{}^{}之类的附加组件来分析查询和应用程序

相关问题 更多 >

    热门问题