Kan vi direkte filtrere på et dokument med code>ReferenceField's felter i en enkelt forespørgsel?
Nej, det er ikke muligt direkte at filtrere et dokument med felterne ReferenceField
da dette ville kræve joins, og mongodb understøtter ikke joins.
I henhold til MongoDB-dokumenter på databasereferencer:
Fra en anden side på det officielle websted:
Så i 1 forespørgsel kan vi ikke begge filtrere opgaver
med en bestemt flagværdi og med det givne user_id
og opgave-id
på Brugeropgaver
model.
Hvordan udfører man så filtreringen?
For at udføre filtreringen i henhold til de påkrævede betingelser skal vi udføre 2 forespørgsler.
I den første forespørgsel vil vi forsøge at filtrere Tasks
model med det givne task_id
og flag
. Derefter vil vi i den anden forespørgsel filtrere Brugeropgaver
model med det givne bruger-id
og opgaven
hentet fra den første forespørgsel.
Eksempel:
Lad os sige, at vi har et user_id
, opgave-id
og vi skal kontrollere, om den relaterede opgave har flag
værdi som 0
.
1. forespørgsel
Vi vil først hente min_opgave
med det givne opgave-id
og flag
som 0
.
my_task = Tasks.objects.get(task_id=task_id, flag=0) # 1st query
2. forespørgsel
Så i den 2. forespørgsel skal du filtrere på UserTask
model med det givne bruger-id
og min_opgave
objekt.
my_user_task = UserTasks.objects.get(user_id=user_id, tasks=my_task) # 2nd query
Du bør kun udføre 2. forespørgsel, hvis du får en my_task
objekt med det givne task_id
og flag
værdi. Du bliver også nødt til at tilføje fejlhåndtering, hvis der ikke er nogen matchende objekter.
Hvad nu hvis vi har brugt EmbeddedDocument
for Opgaver
model?
Lad os sige, at vi har defineret vores Opgaver
dokument som et EmbeddedDocument
og opgaverne
felt i Brugeropgaver
model som et EmbeddedDocumentField
, så for at udføre den ønskede filtrering kunne vi have gjort noget som nedenfor:
my_user_task = UserTasks.objects.get(user_id=user_id, tasks__task_id=task_id, tasks__flag=0)
Hent den særlige my_task
fra listen over opgaver
Ovenstående forespørgsel vil returnere en UserTask
dokument, som vil indeholde alle opgaver
. Vi bliver så nødt til at udføre en form for iteration for at få den ønskede opgave.
For at gøre det kan vi udføre listeforståelse ved hjælp af enumerate()
.Derefter vil det ønskede indeks være det 1. element på den returnerede 1-elementliste.
my_task_index = [i for i,v in enumerate(my_user_task.tasks) if v.flag==0][0]