Можем ли директно да филтрираме документ с ReferenceField's
полета в една заявка?
Не, не е възможно директно да филтрирате документ с полетата на ReferenceField
тъй като това ще изисква присъединявания, а mongodb не поддържа присъединявания.
Според документите на MongoDB относно препратки към бази данни:
От друга страница на официалния сайт:
Така че в 1 заявка не можем и двете да филтрираме tasks
с определена стойност на флаг и с дадения user_id
и task_id
на UserTasks
модел.
Как тогава да извършите филтрирането?
За да извършим филтрирането според необходимите условия, ще трябва да извършим 2 заявки.
В първата заявка ще се опитаме да филтрираме Tasks
модел с дадения task_id
и flag
. След това във втората заявка ще филтрираме UserTasks
модел с дадения user_id
и task
извлечено от първата заявка.
Пример:
Да кажем, че имаме user_id
, task_id
и трябва да проверим дали свързаната задача има flag
стойност като 0
.
Първа заявка
Първо ще извлечем my_task
с дадения task_id
и flag
като 0
.
my_task = Tasks.objects.get(task_id=task_id, flag=0) # 1st query
Втора заявка
След това във втората заявка трябва да филтрирате UserTask
модел с дадения user_id
и my_task
обект.
my_user_task = UserTasks.objects.get(user_id=user_id, tasks=my_task) # 2nd query
Трябва да извършите второ запитване само ако получите my_task
обект с дадения task_id
и flag
стойност. Освен това ще трябва да добавите обработка на грешки в случай, че няма съответстващи обекти.
Ами ако сме използвали EmbeddedDocument
за Tasks
модел?
Да приемем, че сме дефинирали нашите Tasks
документ като EmbeddedDocument
и tasks
поле в UserTasks
модел като EmbeddedDocumentField
, тогава, за да направим желаното филтриране, можехме да направим нещо като по-долу:
my_user_task = UserTasks.objects.get(user_id=user_id, tasks__task_id=task_id, tasks__flag=0)
Получаване на конкретната my_task
от списъка със задачите
Горната заявка ще върне UserTask
документ, който ще съдържа всички tasks
. След това ще трябва да извършим някакъв вид итерация, за да получим желаната задача.
За да направим това, можем да извършим разбиране на списък с помощта на enumerate()
.Тогава желаният индекс ще бъде първият елемент от върнатия списък с 1 елемент.
my_task_index = [i for i,v in enumerate(my_user_task.tasks) if v.flag==0][0]