Programing

여러 인수가있는 필터와 장고의 체인 필터의 차이점

lottogame 2020. 11. 25. 07:27
반응형

여러 인수가있는 필터와 장고의 체인 필터의 차이점


Django에서 다중 인수가있는 필터와 체인 필터의 차이점은 무엇입니까?


생성 된 SQL 문에서 볼 수 있듯이 일부는 의심 할 수있는 "OR"이 아닙니다. WHERE 및 JOIN이 배치되는 방법입니다.

예제 1 (동일한 조인 된 테이블) : https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships에서

Blog.objects.filter(
       entry__headline__contains='Lennon', 
       entry__pub_date__year=2008)

이렇게하면 이 쿼리에서 기대할 수있는 가지 항목이 모두 있는 모든 블로그가 표시 (entry__headline__contains='Lennon') AND (entry__pub_date__year=2008)됩니다.

결과:

Blog with {entry.headline: 'Life of Lennon', entry.pub_date: '2008'}

예 2 (체인)

Blog.objects.filter(
       entry__headline__contains='Lennon'
           ).filter(
       entry__pub_date__year=2008)

이것은 예제 1의 모든 결과를 포함하지만 약간 더 많은 결과를 생성합니다. 먼저 모든 블로그를 (entry__headline__contains='Lennon')필터링 한 다음 결과 필터에서 필터링하기 때문 (entry__pub_date__year=2008)입니다.

차이점은 다음과 같은 결과도 제공한다는 것입니다.

여러 항목이있는 단일 블로그

{entry.headline: '**Lennon**', entry.pub_date: 2000}, 
{entry.headline: 'Bill', entry.pub_date: **2008**}

첫 번째 필터가 평가 될 때 첫 번째 항목 때문에 책이 포함됩니다 (일치하지 않는 다른 항목이 있더라도). 두 번째 필터가 평가되면 두 번째 항목 때문에 책이 포함됩니다.

하나의 테이블 : 하지만 쿼리에 Yuji 및 DTing의 예와 같이 조인 된 테이블이 포함되지 않은 경우. 결과는 동일합니다.


"multiple arguments filter-query"의 결과가 "chained-filter-query"와 다른 경우는 다음과 같습니다.

참조 개체 및 관계를 기반으로 참조 개체를 선택하는 것은 일대 다 (또는 다 대다)입니다.

여러 필터 :

    Referenced.filter(referencing1_a=x, referencing1_b=y)
    #  same referencing model   ^^                ^^

체인 필터 :

    Referenced.filter(referencing1_a=x).filter(referencing1_b=y)

두 쿼리 모두 서로 다른 결과를 출력 할 수 있습니다.
referencing-model의 한 행 이상이 referenced-model의 Referencing1동일한 행을 참조 할 수있는 경우 Referenced. 이 경우에 할 수있다 Referenced: Referencing1이 중 하나를 1 : N (일대) 또는 N : (많은 많은) M 관계 선박.

예:

내 응용 프로그램 my_company에는 두 가지 모델 EmployeeDependent. 의 직원은 my_company부양 가족 이상을 가질 수 있습니다 (즉, 부양 가족은 단일 직원의 아들 / 딸이 될 수있는 반면 직원은 둘 이상의 아들 / 딸을 가질 수 있음).
Ehh, 남편 아내처럼 둘 다 my_company. 1 : m 예를 들었습니다.

그래서, Employee참조 모델이 더 많이 참조 할 수있는 참조 Dependent모델입니다. 이제 다음과 같이 관계 상태를 고려하십시오.

Employee:        Dependent:
+------+        +------+--------+-------------+--------------+
| name |        | name | E-name | school_mark | college_mark |
+------+        +------+--------+-------------+--------------+
| A    |        | a1   |   A    |          79 |           81 |
| B    |        | b1   |   B    |          80 |           60 |
+------+        | b2   |   B    |          68 |           86 |
                +------+--------+-------------+--------------+  

Dependent a1는 직원을 의미 A하고 종속적 b1, b2참조는 직원을 의미 B합니다.

이제 내 쿼리는 다음과 같습니다.

대학과 학교 모두에서 아들 / 딸이있는 직원이 모두 구별 점수 (예 : 75 % 이상)를 가지고 있습니까?

>>> Employee.objects.filter(dependent__school_mark__gte=75,
...                         dependent__college_mark__gte=75)

[<Employee: A>]

출력은 'A'의존적 'a1'은 대학과 학교 모두에서 구별 마크가 있으며 직원 'A'에 의존합니다. 참고 'B'는 'B'자녀의 네더가 대학과 학교 모두에서 구별 마크를 가지고 있기 때문에 선택되지 않았습니다. 관계형 대수 :

종업원 (school_mark> = 75 AND college_mark> = 75) 종속

둘째, 쿼리가 필요한 경우 :

일부 부양 가족이 대학과 학교에서 구별 마크를 가진 모든 직원을 찾으십니까?

>>> Employee.objects.filter(
...             dependent__school_mark__gte=75
...                ).filter(
...             dependent__college_mark__gte=75)

[<Employee: A>, <Employee: B>]

이번에 'B'는 'B'가 두 명의 자녀 (한 명 이상!)가 있고, 한 명은 학교 'b1'에 구별 마크가 있고 다른 하나는 대학 'b2'에 구별 마크가 있기 때문에 선택되었습니다.
필터 순서는 중요하지 않습니다. 위의 쿼리를 다음과 같이 작성할 수도 있습니다.

>>> Employee.objects.filter(
...             dependent__college_mark__gte=75
...                ).filter(
...             dependent__school_mark__gte=75)

[<Employee: A>, <Employee: B>]

결과는 동일합니다! 관계형 대수는 다음과 같습니다.

(직원 (school_mark> = 75) 에 따라 다름) (college_mark> = 75) 종속

참고 :

dq1 = Dependent.objects.filter(college_mark__gte=75, school_mark__gte=75)
dq2 = Dependent.objects.filter(college_mark__gte=75).filter(school_mark__gte=75)

동일한 결과를 출력합니다. [<Dependent: a1>]

Django에서 생성 한 대상 SQL 쿼리를 확인 print qd1.query하고 print qd2.query둘 다 동일합니다 (Django 1.6).

그러나 의미 상 둘 다 나에게 다릅니다 . 첫 번째는 간단한 섹션 σ [school_mark> = 75 AND college_mark> = 75] (종속)이고 두 번째는 느린 중첩 쿼리처럼 보입니다. σ [school_mark> = 75][college_mark> = 75] (종속)).

코드 @codepad 가 필요한 경우

btw, 그것은 문서 @ Spanning 다중 값 관계에 제공 됩니다. 방금 예제를 추가했습니다. 새로운 사람에게 도움이 될 것이라고 생각합니다.


대부분의 경우 쿼리에 대해 가능한 결과 집합은 하나만 있습니다.

체인 필터는 m2m을 다룰 때 사용됩니다.

이걸 고려하세요:

# will return all Model with m2m field 1
Model.objects.filter(m2m_field=1) 

# will return Model with both 1 AND 2    
Model.objects.filter(m2m_field=1).filter(m2m_field=2) 

# this will NOT work
Model.objects.filter(Q(m2m_field=1) & Q(m2m_field=2))

다른 예도 환영합니다.


성능 차이가 큽니다. 그것을 시도하고보십시오.

Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)

의외로 느립니다

Model.objects.filter(condition_a, condition_b, condition_c)

As mentioned in "Effective Django ORM",

  • QuerySets maintain state in memory
  • Chaining triggers cloning, duplicating that state
  • Unfortunately, QuerySets maintain a lot of state
  • If possible, don’t chain more than one filter

You can use the connection module to see the raw sql queries to compare. As explained by Yuji's, for the most part they are equivalent as shown here:

>>> from django.db import connection
>>> samples1 = Unit.objects.filter(color="orange", volume=None)
>>> samples2 = Unit.objects.filter(color="orange").filter(volume=None)
>>> list(samples1)
[]
>>> list(samples2)
[]
>>> for q in connection.queries:
...     print q['sql']
... 
SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange  AND `samples_unit`.`volume` IS NULL)
SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange  AND `samples_unit`.`volume` IS NULL)
>>> 

If you end up on this page looking for how to dynamically build up a django queryset with multiple chaining filters, but you need the filters to be of the AND type instead of OR, consider using Q objects.

An example:

# First filter by type.
filters = None
if param in CARS:
  objects = app.models.Car.objects
  filters = Q(tire=param)
elif param in PLANES:
  objects = app.models.Plane.objects
  filters = Q(wing=param)

# Now filter by location.
if location == 'France':
  filters = filters & Q(quay=location)
elif location == 'England':
  filters = filters & Q(harbor=location)

# Finally, generate the actual queryset
queryset = objects.filter(filters)

If requires a and b then

and_query_set = Model.objects.filter(a=a, b=b)

if requires a as well as b then

chaied_query_set = Model.objects.filter(a=a).filter(b=b)

Official Documents: https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships

Related Post: Chaining multiple filter() in Django, is this a bug?


There is a difference when you have request to your related object, for example

class Book(models.Model):
    author = models.ForeignKey(Author)
    name = models.ForeignKey(Region)

class Author(models.Model):
    name = models.ForeignKey(Region)

request

Author.objects.filter(book_name='name1',book_name='name2')

returns empty set

and request

Author.objects.filter(book_name='name1').filter(book_name='name2')

returns authors that have books with both 'name1' and 'name2'

for details look at https://docs.djangoproject.com/en/dev/topics/db/queries/#s-spanning-multi-valued-relationships

참고URL : https://stackoverflow.com/questions/5542874/difference-between-filter-with-multiple-arguments-and-chain-filter-in-django

반응형