콘텐츠로 이동

가입 및 하위 쿼리

관련 모델을 로드하기 위해 한 테이블을 다른 테이블로 연결하려면 다음 방법을 사용할 수 있습니다.

  • select_related(related: Union[List, str]) -> QuerySet

  • select_all(follow: bool = True) -> QuerySet

  • prefetch_related(related: Union[List, str]) -> QuerySet

  • 모델

    • 모델.로드() 방법
    • 쿼리 세트 에이전트

    • QuerysetProxy.select_related(related: Union[List, str]) 방법

    • QuerysetProxy.select_all(follow: bool=True) 방법
    • QuerysetProxy.prefetch_related(related: Union[List, str]) 방법

관련 선택

select_related(related: Union[List, str]) -> QuerySet

동일한 쿼리 중에 관련 모델을 미리 가져올 수 있습니다.

선택_lated를 사용하면 항상 데이터베이스에 대해 하나의 쿼리만 실행됩니다. 즉, (때로는 복잡한) 조인이 생성되고 나중에 중첩된 모델이 파이썬에서 처리됩니다.

관련 모델을 얻으려면 외래 키 이름을 사용하십시오.

관련 모델 관계를 연결하려면 이름 사이에 이중 밑줄을 사용하십시오.

!!!참고 do 출신인 경우 ormar_lated in do는 단일 관계 유형만 선택할 수 있다는 점에서 ->와 다르지만 ormar에서는 외래 키 관계, 외래 키의 뒷면(가상 자동 생성 키) 및 ManyTo많이에서 상관 관계를 선택할 수 있습니다. 필드(따라서 현재 버전의 모든 관계).

!!!팁 선택한 모델 필드를 제어하려면 필드()를 사용하고 _field() 쿼리 세트 메서드를 제외합니다.

!!!팁 모델의 순서(마스터 또는 중첩)를 제어하려면 순서_by() 메서드를 사용하십시오.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
클래스 앨범(ormar. 모델):
    ormar_config = base_ormar_config 사본()

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)
    is_est_: bool = ormar. 부울(기본값 = 거짓)

클래스 트랙(ormar. 모델):
    ormar_config = base_ormar_config 사본()

    ID: int = ormar. 정수(prial_key = 참)
    앨범: 옵션 [앨범] = ormar. ForeignKey (앨범)
    제목: str = ormar. 문자열(max_long = 100)
    위치: int = ormar. 정수()
    플레이 카운트: int = ormar. 정수(nullable = 참)


# 장고 스타일
앨범 = 앨범을 기다립니다. ts_ ("트랙") .all ()

# 파이썬 스타일
앨범 = Album .ts.t_ (Album .).all ()

# 모든 칼럼 트랙이 있는 앨범을 반환합니다.

문자열 또는 문자열 목록(또는 필드/필드 목록)을 제공할 수 있습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
클래스 스쿨 클래스(ormar. 모델):
    ormar_config = base_ormar_config (테이블 이름 = "학교 수업")

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)
    부서: 옵션 [부서] = ormar. 외래 키(부서, nullable = 거짓)


클래스 카테고리(ormar. 모델):
    ormar_config = base_ormar_config (테이블 이름 = "카테고리")

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)


클래스 학생(ormar. 모델):
    ormar_config = base_ormar_config 사본()

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)
    학교 수업: 선택 사항 [학교 수업] = ormar. 외국인 키(학교 수업)
    카테고리: 옵션 [카테고리] = ormar. 외래 키(카테고리, nullable = True)


클래스 교사(ormar. 모델):
    ormar_config = base_ormar_config 사본()

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)
    학교 수업: 선택 사항 [학교 수업] = ormar. 외국인 키(학교 수업)
    카테고리: 옵션 [카테고리] = ormar. 외래 키(카테고리, nullable = True)


# 장고 스타일
클래스 = 학교 클래스를 기다립니다.ts._ (
    ["교사__ 카테고리", "학생"]).all ()

# 파이썬 스타일
클래스 = 학교 클래스를 기다립니다.ts._ (
    [스쿨클래스.교사.카테고리, 스쿨클래스.학생]).all ()

# 교사 및 교사 카테고리와 함께 수업을 반환합니다.
# 수업 학생뿐만 아니라

Many2많이 필드는 정확히 동일하게 작동합니다. 여기서 Many2많이 필드의 이름을 입력하고 최종 모델을 가져올 수 있습니다.

!!!경고 모든 쿼리 중에 ForeignKey 필드를 nullable(따라서 필수)로 설정하면 nullable 모델이 선택 _lated에 포함되지 않더라도 자동으로 사전 설정됩니다.

!!!행을 반환하지 않는 모든 메서드는 쿼리 세트 인스턴스를 명시적으로 반환하여 함께 연결할 수 있습니다.

1
2
3
따라서 `filter()`,`select_related()`,`limit()` 및 `offset()` 등과 같은 작업을 체인으로 연결할 수 있습니다.

뭔가 `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`

모두 선택

select_all(follow: bool = False) -> QuerySet

기본적으로 모든 ()를 선택할 때 관계가 로드되지 않으며, 다시 선택 _lated ()를 사용할 때 로드해야 할 모든 관계를 명시적으로 지정해야 합니다. 중첩된 관계도 포함하려는 경우 번거로울 수 있습니다.

그렇기 때문에 _all()이 도입되어 모델의 모든 관계가 기본적으로 로드됩니다(모든() 메서드와 반대).

기본적으로 쿼리가 실행되는 상위 모델과 직접 관련된 모델만 추가됩니다.

팔로우=트루를 설정하면 관련 모델의 관련 모델도 추가됩니다.

!!!관련 모델은 모델 세트에 액세스하는 상위 모델과도 관계를 유지하기 때문에 무한 루프에 갇히지 않기 위한 정보입니다.

1
2
3
4
이렇게 하면 이미 방문한 모델이 중첩되어 있지만 로드는 로드되지 않습니다.
모델 A -> 모델 B -> 모델 C -> 모델 A -> 모델 X inside.So 따르십시오.
두 번째 모델 A를 로드하지만 모델 X를 따르지 않습니다.
이러한 종류의 중첩 관계는 수동으로 로드해야 합니다.

샘플 날짜는 다음과 같습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
base_ormar_config = OrmarConfig (
    데이터베이스 = 데이터베이스. 데이터베이스(DATABASE_URL, force_roll back = 참),
    메타데이터 = sqlalchemy. 메타데이터(),
)


클래스 주소(ormar. 모델):
    ormar_config = base_ormar_config (테이블 이름 = "주소")

    ID: int = ormar. 정수(prial_key = 참)
    거리: str = ormar. 문자열(max_long = 100, nullable = 거짓)
    번호: int = ormar. 정수(nullable = 거짓)
    Post_code: str = ormar. 문자열(max_long = 20, nullable = 거짓)



클래스 분기(ormar. 모델):
    ormar_config = base_ormar_config (테이블 이름 = "가지")

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100, nullable = 거짓)
    주소 = ormar. 외래 키(주소)


클래스 컴퍼니(ormar. 모델):
    ormar_config = base_ormar_config (테이블 이름 = "회사")

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100, nullable = 거짓, 이름 = "회사 이름")
    설립: int = ormar. 정수(nullable = 참)
    가지 = ormar. ManyTo많이 (지점)

모든 지점과 주소를 가진 모든 회사를 선택하려면 다음 사항을 문의하기만 하면 됩니다.

1
2
3
4
회사 = 회사를 기다립니다.ts._all (팔로우 = 참).all ()

# 이는 다음과 같습니다.
회사 = 회사를 기다립니다.ts.t_(' __').all()

물론 이 경우 선택 _lated에서 명시적 관계 이름을 발행하는 것은 매우 쉽지만 선택 _all()의 이점은 여러 관계를 가질 때 분명해집니다.

예를 들어 회사에 3개의 관계가 있고 3개의 관계가 모두 3개의 관계가 있는 경우 9개의 관계 문자열을 발행하여 _lated를 선택하고 _all()을 선택하면 관계 이름을 변경할 수 없습니다.

!!!선택 _all()을 필터, 제외 _field 등과 같은 다른 쿼리 세트 메서드와 연결할 수 있습니다. 관계를 제외하려면 제외할 관계의 (또한 중첩된) 이름을 가진 예외 _ 필드() 호출을 사용하십시오.

프리페치 상관 관계

prefetch_related(related: Union[List, str]) -> QuerySet

쿼리 중에 관련 모델을 미리 가져올 수 있지만 _lated를 선택하는 대신 각 후속 모델은 별도의 데이터베이스 쿼리로 가져옵니다.

프리페치_lated를 사용하면 각 모델이 데이터베이스에 대해 하나의 쿼리를 실행하므로 여러 쿼리를 차례로 실행합니다.

관련 모델을 얻으려면 외래 키 이름을 사용하십시오.

관련 모델 관계를 연결하려면 이름 사이에 이중 밑줄을 사용하십시오.

!!!팁 선택한 모델 필드를 제어하려면 필드()를 사용하고 _field() 쿼리 세트 메서드를 제외합니다.

!!!팁 모델의 순서(마스터 또는 중첩)를 제어하려면 순서_by() 메서드를 사용하십시오.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
클래스 앨범(ormar. 모델):
    ormar_config = base_ormar_config 사본()

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)
    is_est_: bool = ormar. 부울(기본값 = 거짓)

클래스 트랙(ormar. 모델):
    ormar_config = base_ormar_config 사본()

    ID: int = ormar. 정수(prial_key = 참)
    앨범: 옵션 [앨범] = ormar. ForeignKey (앨범)
    제목: str = ormar. 문자열(max_long = 100)
    위치: int = ormar. 정수()
    플레이 카운트: int = ormar. 정수(nullable = 참)


# 장고 스타일
앨범 = await Album .ts.prefetch_ 관련("트랙") .all ()

# 파이썬 스타일
앨범 = Album을 기다립니다. ts.prefetch_ (Alum.).all ()


# 앨범을 반환합니다. 모든 칼럼 트랙

문자열 또는 문자열 목록을 제공할 수 있습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
클래스 스쿨 클래스(ormar. 모델):
    ormar_config = base_ormar_config (테이블 이름 = "학교 수업")

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)
    부서: 옵션 [부서] = ormar. 외래 키(부서, nullable = 거짓)


클래스 카테고리(ormar. 모델):
    ormar_config = base_ormar_config (테이블 이름 = "카테고리")

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)


클래스 학생(ormar. 모델):
    ormar_config = base_ormar_config 사본()

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)
    학교 수업: 선택 사항 [학교 수업] = ormar. 외국인 키(학교 수업)
    카테고리: 옵션 [카테고리] = ormar. 외래 키(카테고리, nullable = True)


클래스 교사(ormar. 모델):
    ormar_config = base_ormar_config 사본()

    ID: int = ormar. 정수(prial_key = 참)
    이름: str = ormar. 문자열(max_long = 100)
    학교 수업: 선택 사항 [학교 수업] = ormar. 외국인 키(학교 수업)
    카테고리: 옵션 [카테고리] = ormar. 외래 키(카테고리, nullable = True)


# 장고 스타일
수업 = 학교 수업을 기다립니다. ts.prefetch_ 관련 (
    ["교사__ 카테고리", "학생"]).all ()

# 파이썬 스타일
수업 = 학교 수업을 기다립니다. ts.prefetch_ 관련 (
    [스쿨클래스.교사.카테고리, 스쿨클래스.학생]).all ()
# 교사 및 교사 카테고리와 함께 수업을 반환합니다.
# 수업 학생뿐만 아니라

Many2많이 필드는 정확히 동일하게 작동합니다. 여기서 Many2많이 필드의 이름을 입력하고 최종 모델을 가져올 수 있습니다.

!!!경고: 모든 쿼리 중에 ForeignKey 필드를 nullable(따라서 필수)로 설정하면 nullable 모델이 선택 _lated에 포함되지 않더라도 자동으로 사전 설정됩니다.

!!!행을 반환하지 않는 모든 메서드는 쿼리 세트 인스턴스를 명시적으로 반환하여 함께 연결할 수 있습니다.

1
2
3
따라서 `filter()`,`select_related()`,`limit()` 및 `offset()` 등과 같은 작업을 체인으로 연결할 수 있습니다.

뭔가 `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`

상관 관계 선택 대 사전 추출 상관 관계

-> _lated 또는 prefetch_lated 중 어느 것을 사용해야 합니까?

음, 그것은 정말로 당신의 데이터에 달려 있습니다. 가장 좋은 대답은 직접 사용해보고 시스템 제한 내에서 어떤 것이 더 빠르고 더 나은 성능을 발휘하는지 확인하는 것입니다.

기억해야 할 사항:

성능

쿼리 수: _lated를 선택하면 항상 데이터베이스에 대해 하나의 쿼리를 수행하는 반면 prefetch_lated는 여러 쿼리를 수행합니다. 쿼리(I/O) 작업은 일반적으로 가장 느리지만 반드시 그렇지는 않습니다.

행 수: 표 A에 10,000개의 개체가 있고, 각 개체에는 표 B에 3개의 하위 개체가 있고, 표 B의 각 개체에는 표 C에 2개의 하위 개체가 있다고 가정합니다. 다음과 같습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
                     모델 C
                   /
           모델 B - 모델 C
         / 
모델 A - 모델 B - 모델 C
       \           \ 
        \모델 C
         \
           모델 B - 모델 C
                   \ 
                     모델 C

즉, 선택 _lated는 항상 60,000 행(10,000*3*2)을 반환하고 나중에 10,000 모델로 압축됩니다.

프리페치_lated를 반환하는 라인은 몇 개입니까?

음, 각 모델 B와 C가 고유하면 첫 번째 쿼리에서 10,000개의 행과 두 번째 쿼리에서 30,000개의 행을 반환합니다(표 B에서 A의 하위 항목 3개). 각각은 고유합니다) 및 60,000개의 행(표 B의 각 하위는 고유합니다). 표 C의 모델 B의 두 자녀는 세 번째 쿼리에서 고유합니다.)

이 경우 _lated를 선택하는 것이 더 나은 선택인 것 같습니다. 3개의 프리페치_lated와 비교하여 쿼리를 실행할 뿐만 아니라 100,000개의 프리페치_lated(10+30+60k)와 비교하여 60을 반환합니다. 000줄.

그러나 모든 모델 A가 정확히 동일한 3개의 모델 B를 가지고 있고 모든 모델 C가 정확히 동일한 모델 C를 가지고 있다면 어떨까요? _lated를 선택하면 여전히 60,000개의 행이 반환되고 prefetch_lated는 모델 A의 경우 10,000개의 행, 모델 B의 경우 3개의 행, 모델 C의 경우 2개의 행이 반환됩니다. 총 10,006개의 행이 있습니다. 이제 모델의 구조에 따라(즉, 긴 텍스트() 필드 등이 있는 경우) 프리페치_lated가 더 빠를 수 있지만 하나 대신 세 개의 개별 쿼리를 실행해야 합니다.

기억

Ormar는 로드된 모델에 대한 regedit을 유지하지 않습니다.

즉, 위의 _lated 선택 예에서 항상 10,000개의 모델 A, 30,000개의 모델 B가 있습니다(데이터베이스의 고유 행 수가 3인 경우에도 _lated 처리를 선택하면 각 상위 모델에 대해 새 행이 생성됩니다). 하위 모델). 그리고 60,000 모델 C.

행 1, 10, 100 등이 동일한 모델 B를 공유하고 그 중 하나를 업데이트하면 동일한 자식을 공유하는 나머지 행이 즉시 업데이트되지 않습니다. 데이터베이스에 변경 사항을 저장하는 경우 변경 사항은 다시 로드한 후에만 사용할 수 있습니다(각 하위 항목을 개별적으로 로드하거나 전체 쿼리를 다시 로드). 즉, 각 하위 개체가 새 개체로 인스턴트화되기 때문에 _lated를 선택하면 더 많은 메모리가 사용됩니다.

  • 분명히 그는 자신의 공간을 사용했습니다.

!!!캐싱을 도입하기로 결정한 경우 향후 릴리스에서 변경될 수 있습니다.

경고: 기본적으로 모든 하위(또는 동일한 모델이 두 번 이상 로드되는 이벤트)는 데이터베이스에서 동일한 행을 나타내더라도 완전히 분리되고 구별되는 파이썬 개체입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
비교할 때 True로 평가되므로 위의 예:

```python
# will return True if child1 of both rows is the same child db row 
row1.child1 == row100.child1

# same here:
model1 = await Model.get(pk=1)
model2 = await Model.get(pk=1) # same pk = same row in db
# will return `True`
model1 == model2
```

but

```python
# will return False (note that id is a python `builtin` function not ormar one).
id(row1.child1) == id(ro100.child1)

# from above - will also return False
id(model1) == id(model2)
```

대신 프리페치_lated를 사용하면 고유하게 구별되는 각 하위 모델이 한 번만 Instantiated되고 동일한 하위 모델이 모든 상위 모델 간에 공유됩니다. 즉, 위의 프리페치 _lated 예에서 표 B에 3개의 다른 모델이 있고 표 C에 2개의 다른 모델이 있는 경우 모든 모델 A 인스턴스 간에 5개의 하위 모델만 공유됩니다. 이것은 또한 속성을 업데이트하는 경우 모든 상위 개체가 동일한 하위 개체를 공유하기 때문에 해당 속성을 업데이트합니다.

모델 방법

각 모델 인스턴스에는 저장, 업데이트 또는 로드하는 일련의 방법이 있습니다.

로드

로드() 메서드를 호출하여 ForeignKey 관련 모델을 로드할 수 있습니다.

다른 프로세스에 의해 모델이 변경된 경우 로드()를 사용하여 데이터베이스에서 모델을 새로 고칠 수 있습니다.

!!!팁 모델 방법의 부하() 방법에 대해 자세히 알아보기

QuerysetProxy 방법

관련 ManyTo많이 필드 및 ReverseForeignKey에 직접 액세스하면 관련 모델 목록이 반환됩니다.

그러나 쿼리 세트 API의 하위 집합도 표시되므로 상위 모델에서 직접 필터링, 생성, 관련 모델 선택 등을 할 수 있습니다.

관련 선택

위의 선택 _lated 함수와 정확히 동일하지만 관계의 다른 끝에서 관련 개체를 가져올 수 있습니다.

!!!QuerysetProxy에 대해 자세히 알아보려면 QuerysetProxy 섹션을 방문하십시오.

모두 선택

위의 선택 _all 함수와 정확히 동일하지만 관계의 다른 끝에서 관련 개체를 가져올 수 있습니다.

!!!QuerysetProxy에 대해 자세히 알아보려면 QuerysetProxy 섹션을 방문하십시오.

프리페치 상관 관계

위의 prefetch_lated 함수와 정확히 동일하지만 관계의 다른 끝에서 관련 개체를 가져올 수 있습니다.

!!!QuerysetProxy에 대해 자세히 알아보려면 QuerysetProxy 섹션을 방문하십시오.