Possiamo filtrare direttamente un documento con ReferenceField's
campi in una singola query?
No, non è possibile filtrare direttamente un documento con i campi di ReferenceField
poiché ciò richiederebbe join e mongodb non supporta i join.
Secondo i documenti MongoDB su riferimenti al database:
Da un'altra pagina sul sito ufficiale:
Quindi in 1 query, non possiamo entrambi filtrare tasks
con un particolare valore di flag e con il dato user_id
e task_id
su UserTasks
modello.
Come eseguire il filtraggio, allora?
Per eseguire il filtraggio secondo le condizioni richieste, dovremo eseguire 2 query.
Nella prima query cercheremo di filtrare le Tasks
modello con il dato task_id
e flag
. Quindi, nella seconda query, filtreremo UserTasks
modello con il dato user_id
e l'tasks
recuperato dalla prima query.
Esempio:
Diciamo che abbiamo un user_id
, task_id
e dobbiamo verificare se l'attività correlata ha flag
valore come 0
.
1a richiesta
Per prima cosa recupereremo my_task
con il dato task_id
e flag
come 0
.
my_task = Tasks.objects.get(task_id=task_id, flag=0) # 1st query
2a richiesta
Quindi nella seconda query, devi filtrare su UserTask
modello con il dato user_id
e my_task
oggetto.
my_user_task = UserTasks.objects.get(user_id=user_id, tasks=my_task) # 2nd query
Dovresti eseguire la seconda query solo se ottieni un my_task
oggetto con il dato task_id
e flag
valore. Inoltre, dovrai aggiungere la gestione degli errori nel caso non ci siano oggetti corrispondenti.
E se avessimo utilizzato EmbeddedDocument
per le Tasks
modello?
Diciamo che abbiamo definito le nostre Tasks
documento come EmbeddedDocument
e le tasks
campo in UserTasks
modello come EmbeddedDocumentField
, quindi per eseguire il filtraggio desiderato avremmo potuto fare qualcosa come di seguito:
my_user_task = UserTasks.objects.get(user_id=user_id, tasks__task_id=task_id, tasks__flag=0)
Ottenere il particolare my_task
dall'elenco delle attività
La query precedente restituirà un UserTask
documento che conterrà tutte le tasks
. Dovremo quindi eseguire una sorta di iterazione per ottenere l'attività desiderata.
Per fare ciò, possiamo eseguire la comprensione dell'elenco usando enumerate()
.Quindi l'indice desiderato sarà il primo elemento dell'elenco di 1 elemento restituito.
my_task_index = [i for i,v in enumerate(my_user_task.tasks) if v.flag==0][0]