¿Podemos filtrar directamente en un documento con ReferenceField's
campos en una sola consulta?
ReferenceField
ya que hacer esto requeriría uniones y mongodb no admite uniones.
Según los documentos de MongoDB en referencias de bases de datos:
De otra página en el sitio oficial:
Entonces, en 1 consulta, no podemos filtrar tasks
con un valor de bandera particular y con el user_id
dado y task_id
en UserTasks
modelo.
¿Cómo realizar el filtrado entonces?
Para realizar el filtrado según las condiciones requeridas, necesitaremos realizar 2 consultas.
En la primera consulta intentaremos filtrar las Tasks
modelo con el task_id
dado y flag
. Luego, en la segunda consulta, filtraremos UserTasks
modelo con el user_id
dado y la task
recuperado de la primera consulta.
Ejemplo:
Digamos que tenemos un user_id
, task_id
y necesitamos verificar si la tarea relacionada tiene flag
valor como 0
.
1ra Consulta
Primero recuperaremos el my_task
con el task_id
dado y flag
como 0
.
my_task = Tasks.objects.get(task_id=task_id, flag=0) # 1st query
Segunda consulta
Luego, en la segunda consulta, debe filtrar en UserTask
modelo con el user_id
dado y my_task
objeto.
my_user_task = UserTasks.objects.get(user_id=user_id, tasks=my_task) # 2nd query
Debe realizar la segunda consulta solo si obtiene un my_task
objeto con el task_id
dado y flag
valor. Además, deberá agregar el manejo de errores en caso de que no haya objetos coincidentes.
¿Qué pasa si hemos usado EmbeddedDocument
? para las Tasks
modelo?
Digamos que hemos definido nuestras Tasks
documento como un EmbeddedDocument
y las tasks
campo en UserTasks
modelo como un EmbeddedDocumentField
, luego, para hacer el filtrado deseado, podríamos haber hecho algo como lo siguiente:
my_user_task = UserTasks.objects.get(user_id=user_id, tasks__task_id=task_id, tasks__flag=0)
Obteniendo my_task
en particular de la lista de tareas
La consulta anterior devolverá una UserTask
documento que contendrá todas las tasks
. Entonces tendremos que realizar algún tipo de iteración para obtener la tarea deseada.
Para hacer eso, podemos realizar la comprensión de la lista usando enumerate()
.Entonces el índice deseado será el primer elemento de la lista de 1 elemento devuelta.
my_task_index = [i for i,v in enumerate(my_user_task.tasks) if v.flag==0][0]