Trabalhando com Conjuntos no Django
No Django, os métodos union
, intersection
, difference
e distinct
são métodos para manipulação de conjuntos de QuerySets. Eles permitem combinar, interseccionar, subtrair e remover valores duplicados dos resultados de consultas, respectivamente. Para ilustrar, consideramos a seguinte tabela inicial no banco de dados:
id | name | age |
---|---|---|
1 | Bob | 42 |
2 | Tom | 38 |
3 | Sam | 28 |
4 | Alice | 32 |
5 | Tom | 22 |
union
O método union()
combina dois ou mais QuerySets, correspondendo ao operador SQL UNION
. Por padrão, os resultados são únicos, ou seja, valores duplicados são removidos.
toms = Person.objects.filter(name="Tom")
print(toms.values())
# <QuerySet [{'id': 2, 'name': 'Tom', 'age': 38}, {'id': 5, 'name': 'Tom', 'age': 22}]>
bobs = Person.objects.filter(name="Bob")
print(bobs.values())
# <QuerySet [{'id': 1, 'name': 'Bob', 'age': 42}]>
# Combinação padrão (valores únicos)
people = toms.union(bobs)
print(people.values())
# <QuerySet [{'id': 1, 'name': 'Bob', 'age': 42}, {'id': 2, 'name': 'Tom', 'age': 38}, {'id': 5, 'name': 'Tom', 'age': 22}]>
Para inluir valores duplicados, o método union
aceita o argumento all=Tru
:
# Incluindo valores duplicados
people = toms.values("name").union(bobs, all=True)
print(people)
# <QuerySet [{'name': 'Tom'}, {'name': 'Tom'}, {'name': 'Bob'}]>
intersection
O método intersection()
retorna objetos presentes em todos os QuerySets fornecidos, equivalente ao operador SQL INTERSECT
.
toms = Person.objects.filter(name="Tom")
print(toms.values())
# <QuerySet [{'id': 2, 'name': 'Tom', 'age': 38}, {'id': 5, 'name': 'Tom', 'age': 22}]>
less35 = Person.objects.filter(age__lt=35)
print(less35.values())
# <QuerySet [{'id': 3, 'name': 'Sam', 'age': 28}, {'id': 4, 'name': 'Alice', 'age': 32}, {'id': 5, 'name': 'Tom', 'age': 22}]>
# Interseção dos QuerySets
people = toms.intersection(less35)
print(people.values())
# <QuerySet [{'id': 5, 'name': 'Tom', 'age': 22}]>
No exemplo, apenas o registro com id=5
está presente em ambos os QuerySets.
difference
O método difference()
retorna os objetos que estão no primeiro QuerySet, mas não nos outros, equivalente ao operador SQL EXCEPT
.
toms = Person.objects.filter(name="Tom")
print(toms.values())
# <QuerySet [{'id': 2, 'name': 'Tom', 'age': 38}, {'id': 5, 'name': 'Tom', 'age': 22}]>
less35 = Person.objects.filter(age__lt=35)
print(less35.values())
# <QuerySet [{'id': 3, 'name': 'Sam', 'age': 28}, {'id': 4, 'name': 'Alice', 'age': 32}, {'id': 5, 'name': 'Tom', 'age': 22}]>
# Diferença entre os QuerySets
people = toms.difference(less35)
print(people.values())
# <QuerySet [{'id': 2, 'name': 'Tom', 'age': 38}]>
No exemplo, o registro com id=2
está presente no primeiro QuerySet, mas não no segundo, e é retornado como resultado.
distinct()
O método distinct()
elimina valores duplicados de um QuerySet. Ele é útil, por exemplo, para obter uma lista de nomes únicos dos usuários.
# Sem distinct
people = Person.objects.values_list("name", flat=True)
print(people)
# <QuerySet ['Bob', 'Tom', 'Sam', 'Alice', 'Tom']>
# Com distinct
people = Person.objects.values_list("name", flat=True).distinct()
print(people)
# <QuerySet ['Bob', 'Tom', 'Sam', 'Alice']>
No exemplo acima, distinct()
remove o segundo "Tom" do resultado.
Documentação oficial: