tortoise-orm icon indicating copy to clipboard operation
tortoise-orm copied to clipboard

Filtering two Q expressions across two ManyToMany relationships between the same tables

Open hcastilho opened this issue 2 years ago • 1 comments

Describe the bug Filtering two Q expressions across two ManyToMany relationships between the same tables returns incorrect results.

To Reproduce

class User(Model):
    username = fields.TextField()

class Task(Model):
    reviewers = fields.ManyToManyField(
        "User",
        related_name="task_reviewers",
        null=True,
        through="task_reviewers",
    )
    assignees = fields.ManyToManyField(
        "User",
        related_name="task_assignees",
        null=True,
        through="task_assignees",
models.Task.filter(Q(assignees__username='username')).values_list("id").sql()
'SELECT "task"."id" "0" 
FROM "task" 
LEFT OUTER JOIN "task_assignees" ON "task"."id"="task_assignees"."task_id" 
LEFT OUTER JOIN "user" ON "task_assignees"."user_id"="user"."id" 
WHERE "user"."username"=\'username\''
models.Task.filter(Q(assignees__username='username') | Q(reviewers__username='username')).values_list("id").sql()
'SELECT "task"."id" "0" 
FROM "task" 
LEFT OUTER JOIN "task_assignees" ON "task"."id"="task_assignees"."task_id" 
LEFT OUTER JOIN "user" ON "task_assignees"."user_id"="user"."id" 
LEFT OUTER JOIN "task_reviewers" ON "task"."id"="task_reviewers"."task_id" 
WHERE "user"."username"=\'username\' OR "user"."username"=\'username\''

This query is only selecting users on the task_assignees through table.

Expected behavior Should query users correctly.

hcastilho avatar Feb 01 '23 19:02 hcastilho

create_task_id_list = await DpTask.filter(by_create_at__id=user_id).values_list("id", flat=True) join_task_id_list = await DpTask.filter(by_join_list__id__in=[user_id]).values_list("id", flat=True) visible_task_id_list = await DpTask.filter(by_visible_list__id__in=[user_id]).values_list("id", flat=True) task_id_list = sorted(list(set(create_task_id_list + join_task_id_list + visible_task_id_list))) q &= Q(by_visible_list__id__isnull=True, status_type=StatusType.enable, end_time__gt=time_now) | Q(id__in=task_id_list)

you can try it, use id__in

sleep1223 avatar Jan 11 '25 06:01 sleep1223