Python NDB/DB용 GQL 참조

GQL은 App Engine Datastore에서 항목이나 키를 검색하기 위한 SQL과 유사한 언어입니다. GQL 쿼리의 구문은 SQL의 구문과 유사합니다. 이 페이지는 Python NDB 및 DB 클라이언트 라이브러리에서 GQL을 사용하기 위한 참조 문서입니다.

GQL 구조는 SQL 구조와 거의 일치합니다. GQL kind(종류)는 SQL 테이블, GQL entity(항목)는 SQL 행, GQL property(속성)는 SQL 열과 같다고 할 수 있습니다. 단, SQL 행-열 조회는 단일 값인데 반해 GQL의 속성 값은 목록일 수 있습니다.

GQL 버전

쿼리를 실행하는 위치에 따라 서로 다른 버전의 GQL이 필요합니다. GQL 참조 문서에는 다음 두 가지가 있습니다.

  • Python NDB/DB용 GQL 참조 - NDB 및 DB 클라이언트 라이브러리에서 사용되는 GQL 문법을 확인할 수 있습니다(이 페이지의 참조 사용).

  • GQL 참조 - 최신 Datastore API와 Google Cloud Console Datastore 뷰어에서 사용되는 GQL 문법을 확인할 수 있습니다.

구문

Python NDB/DB용 GQL 구문은 다음과 같이 요약할 수 있습니다.

SELECT [DISTINCT] [* | <property list> | __key__]
  [FROM <kind>]
  [WHERE <condition> [AND <condition> ...]]
  [ORDER BY <property> [ASC | DESC] [, <property> [ASC | DESC] ...]]
  [LIMIT [<offset>,]<count>]
  [OFFSET <offset>]

  <property list> := <property> [, <property> ...]
  <condition> := <property> {< | <= | > | >= | = | != } <value>
  <condition> := <property> IN <list>
  <condition> := ANCESTOR IS <entity or key>
  <list> := (<value> [, <value> ...]])

SQL과 마찬가지로 GQL 키워드도 대소문자를 구분하지 않습니다. 종류 및 속성 이름은 대소문자를 구분합니다.

GQL은 SELECT 문만 지원합니다.

GQL 쿼리는 요청된 종류의 전체 항목, 프로젝션된 항목 또는 를 0개 이상 반환합니다. 모든 GQL 쿼리는 항상 SELECT *, SELECT __key__ SELECT <property list>로 시작합니다. 여기서 property는 쿼리에서 반환할 쉼표로 구분된 하나 이상의 항목 속성 목록입니다. GQL 쿼리는 SQL과 같은 '조인' 쿼리를 수행할 수 없습니다.

팁: SELECT __key__ or SELECT <property list> 쿼리는 SELECT * 쿼리보다 더 빠르면서 CPU 시간은 더 적게 사용합니다.

선택사항인 DISTINCT(실험용) 절은 결과 집합에 완전히 고유한 결과만 반환되도록 지정합니다. 그러면 프로젝션되는 속성 값이 동일한 항목의 첫 번째 결과만 반환됩니다.

선택사항인 FROM 절은 결과 집합을 지정된 종류의 항목으로만 제한합니다. FROM 절이 없는 쿼리는 비구분 쿼리라고 하며 __key__ 속성을 지정하는 WHERE 절만 포함할 수 없습니다.

선택사항인 WHERE 절은 하나 이상의 조건을 충족하는 항목만 포함하도록 결과 집합을 필터링합니다. 각 조건은 비교 연산자를 사용하여 항목의 속성을 값과 비교합니다. AND 키워드로 여러 조건을 지정할 경우 모든 조건을 충족하는 항목만이 쿼리에서 반환됩니다. GQL에는 OR 연산자가 없습니다. 하지만 OR의 기능을 제한된 형태로 제공하는 IN 연산자가 있습니다.

IN 연산자는 속성 값을 목록의 각 항목과 비교합니다. IN 연산자는 여러 개의 = 쿼리(값별로 하나씩)가 OR로 연결된 것과 같습니다. 지정된 속성의 값이 목록의 값과 동일한 항목이 쿼리 결과로 반환될 수 있습니다.

참고: IN 연산자와 != 연산자는 실제로는 여러 쿼리를 사용합니다. 예를 들어 IN 연산자는 목록의 각 항목에 대해 개별적으로 기본 Datastore 쿼리를 실행합니다. 반환되는 항목은 모든 기본 Datastore 쿼리의 교차 곱 결과이며, 중복 항목은 삭제됩니다. 단일 GQL 쿼리에는 최대 30개의 데이터 저장소 쿼리가 허용됩니다.

조건은 또한 ANCESTOR IS 연산자를 사용하여 항목에 지정된 상위 항목이 있는지 여부도 테스트할 수 있습니다. 값은 상위 항목의 모델 인스턴스 또는 입니다. 상위 항목에 대한 자세한 내용은 키 및 항목 그룹을 참조하세요.

비교의 왼쪽에는 항상 속성 이름이 옵니다. 일반적인 속성 이름은 영숫자로 구성되며 필요에 따라 밑줄과 점을 함께 사용할 수 있습니다. 즉, 정규 표현식 [a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)*에 해당합니다.

주의: 인쇄할 수 있는 다른 문자를 포함하는 속성 이름은 큰따옴표로 묶어야 합니다. 예를 들면 "first-name"입니다. 공백이나 인쇄할 수 없는 문자는 속성 이름에 사용할 수 없습니다.

비교의 오른쪽에는 다음 중 하나가 올 수 있습니다(속성의 데이터 유형에 따라 다름).

  • 작은따옴표로 묶은 문자열 형태의 str 리터럴. 문자열의 작은따옴표 문자는 ''로 이스케이프해야 합니다. 예를 들면 'Joe''s Diner'입니다.
  • 정수 또는 부동 소수점 숫자 리터럴. 예를 들면 42.7입니다.
  • 부울 리터럴(TRUE 또는 FALSE)
  • null 값을 나타내는 NULL 리터럴(Python의 경우 None)
  • 숫자 값 또는 문자열 표현을 사용하는 다음 형식의 날짜/시간, 날짜 또는 시간 리터럴:
    • DATETIME(year, month, day, hour, minute, second)
    • DATETIME('YYYY-MM-DD HH:MM:SS')
    • DATE(year, month, day)
    • DATE('YYYY-MM-DD')
    • TIME(hour, minute, second)
    • TIME('HH:MM:SS')
  • 문자열로 인코딩된 키종류 및 키 이름/ID의 전체 경로를 포함하는 항목 키 리터럴

    • KEY('encoded key')
    • KEY('kind', 'name'/ID [, 'kind', 'name'/ID...])
  • 사용자의 이메일 주소를 포함하는 User 객체 리터럴
    USER('email-address')
  • 위도 및 경도를 부동 소수점 값으로 포함하는 GeoPt 리터럴:
    GEOPT(lat, long)
  • 바인딩된 매개변수 값. 쿼리 문자열에서 위치 매개변수는 번호로 참조되고(title = :1), 키워드 매개변수는 이름으로 참조됩니다(title = :mytitle).

참고: property = NULL 형식의 조건은 해당 속성의 Datastore에 null 값이 명시적으로 저장되어 있는지 여부를 확인합니다. 이는 항목에 해당 속성에 대해 어떤 값이 없는지 여부를 확인하는 것과는 다릅니다. 속성을 참조하는 데이터 저장소 쿼리는 해당 속성에 대한 값이 없는 항목은 반환하지 않습니다.

바인딩된 매개변수는 GqlQuery 생성자나 모델 클래스의 gql() 메서드에 전달된 위치 인수 또는 키워드 인수로 바인딩될 수 있습니다. 해당하는 값 리터럴 구문이 없는 목록 데이터 유형 등의 속성 데이터 유형은 매개변수 바인딩을 사용하여 지정해야 합니다. GqlQuery 인스턴스가 유지되는 동안 효과적인 쿼리 재사용 등을 목적으로 bind() 메서드를 사용하여 매개변수 바인딩을 다시 바인딩할 수 있습니다.

선택사항인 ORDER BY 절은 지정된 속성에 따라 결과를 오름차순(ASC) 또는 내림차순(DESC)으로 정렬해야 함을 나타냅니다. ORDER BY 절에서는 여러 정렬 순서를 쉼표로 구분된 목록으로 지정하며 각 정렬 순서는 왼쪽에서 오른쪽으로 평가됩니다. 방향을 지정하지 않을 경우 기본값은 ASC입니다. ORDER BY 절을 지정하지 않으면 결과 순서가 정의되지 않고 시간에 지남에 따라 변경될 수 있습니다.

선택사항인 LIMIT 절을 사용하면 쿼리에서 처음 <count>개의 항목이 반환된 후 더 이상 결과가 반환되지 않습니다. 지정된 수만큼의 결과를 건너뛴 후에 반환할 첫 번째 결과를 찾으려는 경우 LIMIT 절에 <offset>도 포함할 수 있습니다. LIMIT 절이 없는 경우에는 선택사항인 OFFSET 절에서 <offset>을 지정할 수 있습니다.

참고: GQL 쿼리 문자열의 OFFSETfetch() 메서드의 offset 매개변수와 마찬가지로 Datastore에서 가져오는 항목의 수를 줄이지 않습니다. 단지 fetch() 메서드가 어떤 결과를 반환할지에만 영향을 줍니다. 오프셋을 사용하는 쿼리의 성능은 오프셋 크기 및 제한 크기와 비례합니다.

GQL 쿼리 실행, 매개변수 바인딩, 결과 액세스에 대한 자세한 내용은 GqlQuery 클래스와 Model.gql() 클래스 메서드를 참조하세요.

예시

from google.appengine.ext import db

class Person(db.Model):
  name = db.StringProperty()
  age = db.IntegerProperty()

# We use a unique username for the Entity's key.
amy = Person(key_name='amym', name='Amy', age=48)
amy.put()
Person(key_name='bettyd', name='Betty', age=42).put()
Person(key_name='charliec', name='Charlie', age=32).put()
Person(key_name='charliek', name='Charlie', age=29).put()
Person(key_name='eedna', name='Edna', age=20).put()
Person(key_name='fredm', name='Fred', age=16, parent=amy).put()
Person(key_name='georgemichael', name='George').put()

연령이 18세에서 35세 사이인 Person 종류의 모든 항목(즉, 두 명의 Charlie와 Edna)을 찾으려면 다음 쿼리를 사용합니다.

SELECT * FROM Person WHERE age >= 18 AND age <= 35

연령이 가장 많은 Person 종류의 항목 세 개(즉, Amy, Betty, Charlie)를 찾으려면 다음 쿼리를 사용합니다.

SELECT * FROM Person ORDER BY age DESC LIMIT 3

이름이 'Betty' 또는 'Charlie'인 Person 종류의 항목을 찾으려면 다음 쿼리를 사용합니다.

SELECT * FROM Person WHERE name IN ('Betty', 'Charlie')

Personname 값만 반환하려면 다음 쿼리를 사용합니다.

SELECT name FROM Person

Personname 값만 age 순으로 정렬하여 반환하려면 다음 쿼리를 사용합니다.

SELECT name FROM Person ORDER BY age

Person 종류이고 연령이 None인 항목의 키(즉, KEY('Person', 'georgemichael'))를 찾으려면 다음 쿼리를 사용합니다.

SELECT __key__ FROM Person WHERE age = NULL

종류에 상관없이 Amy의 항목 그룹에 포함된 모든 항목(즉, Amy, Fred)을 찾으려면 다음 쿼리를 사용합니다.

SELECT * WHERE __key__ HAS ANCESTOR KEY(Person, 'Amy')

키로 찾으려면 조건의 왼쪽에서 __key__를 사용하면 됩니다. 예를 들어 다음 쿼리를 사용하면 사용자 이름이 'a'로 시작하는 모든 Person 항목을 확인할 수 있습니다.

SELECT * FROM Person WHERE __key__ >= KEY('Person', 'a') AND __key__ < KEY('Person', 'b')

참고: __key__에 같음 연산을 사용하는 쿼리를 작성하기보다는 get()을 사용하여 항목을 바로 가져오는 것이 좋습니다.