참고: 새로운 애플리케이션을 빌드하는 개발자는 NDB 클라이언트 라이브러리를 사용하는 것이 좋습니다. NDB 클라이언트 라이브러리는 이 클라이언트 라이브러리와 비교할 때 Memcache API를 통한 자동 항목 캐싱과 같은 여러 이점이 있습니다. 현재 이전 DB 클라이언트 라이브러리를 사용 중인 경우 DB에서 NDB로의 마이그레이션 가이드를 참조하세요.
Datastore는 일부 메타데이터에 프로그래매틱 방식으로 액세스 권한을 제공하여 메타프로그래밍을 통해 백엔드 관리 기능을 구현하고 일관된 캐싱을 단순화합니다. 또한 유사한 목적, 예를 들면 애플리케이션에 커스텀 Datastore 뷰어를 빌드하는 데도 사용할 수 있습니다. 사용 가능한 메타데이터에는 항목 그룹, 네임스페이스, 항목 종류, 애플리케이션에서 사용하는 속성에 대한 정보와 각 속성의 속성 표현이 포함됩니다.
Google Cloud console의 Datastore 대시보드도 애플리케이션에 대한 일부 메타데이터를 제공하지만 대시보드에 표시되는 데이터는 몇 가지 중요한 점에서 이러한 함수가 반환하는 데이터와 다릅니다.
- 최신 정보. API를 사용한 메타데이터 읽기는 최신 데이터를 가져오며 이때 대시보드의 데이터는 매일 한 번씩만 업데이트됩니다.
- 콘텐츠. 대시보드 메타데이터 중 일부는 API를 통해 제공되지 않으며 반대의 경우도 마찬가지입니다.
- 속도. 메타데이터 가져오기 및 쿼리는 Datastore 가져오기 및 쿼리와 동일한 방식으로 청구됩니다. 네임스페이스, 종류, 속성에 정보를 가져오는 메타데이터 쿼리는 일반적으로 느린 속도로 실행됩니다. 일반적으로 N개의 항목을 반환하는 하나의 메타데이터 쿼리는 각각 하나의 항목을 반환하는 N개의 일반 쿼리와 비슷한 시간이 걸립니다. 그뿐만 아니라 속성 표현 쿼리(키 전용이 아닌 속성 쿼리)는 키 전용 속성 쿼리보다 느립니다. 항목 그룹 메타데이터의 메타데이터 가져오기는 일반 항목 가져오기보다 다소 빠르게 실행됩니다.
도우미 함수
다음 함수는 메타데이터 정보를 가져옵니다.
get_entity_group_version()
은 항목 그룹의 버전 번호를 가져옵니다. 이 함수는 마지막으로 버전 번호를 가져온 후에 그룹의 항목이 변경되었는지 확인하는 데 유용합니다.get_namespaces()
는 모든 애플리케이션 네임스페이스의 이름 또는 지정한 범위의 네임스페이스의 이름이 포함된 목록을 반환합니다.get_kinds()
는 모든 애플리케이션 항목 종류의 이름 또는 지정한 범위의 항목 종류의 이름이 포함된 목록을 반환합니다.get_properties_of_kind()
는 지정한 항목 종류와 연관된 애플리케이션의 모든 색인이 생성된 속성의 이름 또는 지정한 범위의 색인이 생성된 속성의 이름이 포함된 목록을 반환합니다. 색인이 생성되지 않은 속성은 포함되지 않습니다.get_representations_of_kind()
는 지정한 항목 종류와 연관된 색인이 생성된 모든 애플리케이션 속성의 표현 또는 지정한 범위의 색인이 생성된 속성의 표현이 포함된 사전을 반환합니다. 이 사전은 각 속성의 이름을 해당 속성의 표현으로 이루어진 목록에 매핑합니다. 색인이 생성되지 않은 속성은 포함되지 않습니다.
항목 그룹 메타데이터
Cloud Datastore는 항목 그룹의 '버전'에 대한 액세스를 제공합니다. 버전은 항목 그룹이 변경될 때마다 반드시 증가하는 값이며 전적으로 양수입니다.
다음 예시는 항목 그룹의 버전을 가져오는 방법을 보여줍니다.
from google.appengine.ext import db
from google.appengine.ext.db import metadata
class Simple(db.Model):
x = db.IntegerProperty()
entity1 = Simple(x=11)
entity1.put()
# Print entity1's entity group version
print 'version', metadata.get_entity_group_version(entity1)
# Write to a different entity group
entity2 = Simple(x=22)
entity2.put()
# Will print the same version, as entity1's entity group has not changed
print 'version', metadata.get_entity_group_version(entity1)
# Change entity1's entity group by adding a new child entity
entity3 = Simple(x=33, parent=entity1.key())
entity3.put()
# Will print a higher version, as entity1's entity group has changed
print metadata.get_entity_group_version(entity1)
이전 동작
이전 항목 그룹 버전 동작에서는 항목 그룹 버전이 항목 그룹 변경시에만 증가합니다. 예를 들어 이전 항목 그룹 메타데이터 동작은 항목 그룹에서 복잡한 상위 쿼리의 일관된 캐시를 유지하는 데 사용될 수 있습니다.
이 예시에서는 쿼리 결과(일치하는 결과 수)를 캐시하고 항목 그룹 버전의 이전 동작을 사용하여 캐시된 값이 최신 버전의 값일 때만 이 값을 사용합니다.
from google.appengine.api import memcache
from google.appengine.ext import db
from google.appengine.ext.db import metadata
def count_entity_group(entity_group_key):
"""Count the entities in the specified entity group."""
# Check if we have a cached version of the current entity group count
cached = memcache.get(str(entity_group_key))
if cached:
(version, count) = cached
# Is the cached value for the current version?
if version == metadata.get_entity_group_version(entity_group_key):
return count
def tx():
# Need to actually count entities. Using a transaction to get a consistent
# count and entity group version.
count = db.Query(keys_only=True).ancestor(entity_group_key).count(limit=5000)
# Cache the count and the entity group version
version = metadata.get_entity_group_version(entity_group_key)
memcache.set(str(entity_group_key), (version, count))
return count
return db.run_in_transaction(tx)
get_entity_group_version()
은 한 번도 기록되지 않은 항목 그룹에 None
을 반환할 수 있습니다.
__version__
속성이 포함된 특별한 유사 항목에서 get()
을 호출하여 항목 그룹 버전을 가져올 수 있습니다. 자세한 내용은 EntityGroup에 대한 참조 문서를 확인하세요.
메타데이터 쿼리
이전 섹션에서 설명한 도우미 함수가 요구사항을 충족하지 않으면 명시적인 메타데이터 쿼리를 사용하여 보다 정교하거나 유연한 메타데이터 요청을 실행할 수 있습니다. Python에서 이러한 쿼리의 모델 클래스는 google.appengine.ext.db.metadata
패키지에서 정의됩니다. 이러한 모델은 메타데이터 쿼리용으로 예약된 특수한 항목 종류를 제공합니다.
모델 클래스 | 항목 종류 |
---|---|
Namespace |
__namespace__ |
Kind |
__kind__ |
Property |
__property__ |
이러한 모델과 종류는 이미 애플리케이션에 존재할 가능성이 있는 이름이 같은 다른 모델 및 종류와 충돌하지 않습니다. 이러한 특수 종류를 쿼리하면 원하는 메타데이터가 포함된 항목을 검색할 수 있습니다.
메타데이터 쿼리에서 반환되는 항목은 Datastore의 현재 상태에 따라 동적으로 생성됩니다. Namespace
, Kind
또는 Property
모델 클래스의 로컬 인스턴스를 만들 수 있지만 이러한 인스턴스를 Datastore에 저장하려고 시도하면 BadRequestError
예외가 발생하고 실패합니다.
두 클래스 중 하나에 속한 쿼리 객체를 사용하여 메타데이터 쿼리를 실행할 수 있습니다.
- 슈퍼클래스 메서드
Model.all()
에서 상속된 클래스 메서드Namespace.all()
,Kind.all()
또는Property.all()
에서 반환된Query
객체 - GQL 스타일 쿼리의
GqlQuery
객체
다음 예시는 애플리케이션의 모든 항목 종류의 이름을 반환합니다.
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
for k in Kind.all():
print "kind: '%s'" % k.kind_name
네임스페이스 쿼리
애플리케이션에서 네임스페이스 API를 사용하는 경우 네임스페이스 쿼리를 사용하여 애플리케이션의 항목에서 사용되는 모든 네임스페이스를 찾을 수 있습니다. 이 방법으로 여러 네임스페이스에 대한 관리 기능과 같은 작업을 수행할 수 있습니다.
네임스페이스 쿼리는 키 이름이 네임스페이스의 이름인 특수한 종류의 __namespace__
항목을 반환합니다. 단, 빈 문자열 ""
로 지정된 기본 네임스페이스는 예외입니다. 빈 문자열이 유효한 키 이름이 아니기 때문에 이 네임스페이스는 대신 숫자 ID 1
로 키가 지정됩니다. 이 유형의 쿼리는 값이 항목 키인 특수한 유사 속성 __key__
의 범위에서만 필터링을 지원합니다. 결과는 __key__
값의 오름차순으로 정렬할 수 있습니다(내림차순 불가). __namespace__
항목에 속성이 없기 때문에 키 전용 및 키 전용이 아닌 쿼리가 모두 동일한 정보를 반환합니다.
네임스페이스 항목은 모델 클래스 google.appengine.ext.db.metadata.Namespace
의 인스턴스입니다. 항목 키에서 계산된 문자열 속성 namespace_name
은 해당 네임스페이스의 이름을 반환합니다.
키에 숫자 ID 1
이 있으면 이 속성은 빈 문자열을 반환합니다. 쿼리를 용이하게 하도록 Namespace
모델은 다음과 같은 클래스 메서드를 제공합니다.
Namespace.key_for_namespace()
는 네임스페이스 이름에서__namespace__
키를 빌드합니다.Namespace.key_to_namespace()
는 지정한__namespace__
키에 해당하는 네임스페이스 이름을 반환합니다.
예를 들어 다음은 도우미 함수 get_namespaces()
의 구현입니다. 이 함수는 모든 애플리케이션 네임스페이스의 이름(또는 지정한 이름 두 개(start
와 end
) 사이의 범위에 있는 이름)이 포함된 목록을 반환합니다.
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Namespace
def get_namespaces(start=None, end=None):
# Start with unrestricted namespace query
q = Namespace.all()
# Limit to specified range, if any
if start is not None:
q.filter('__key__ >=', Namespace.key_for_namespace(start))
if end is not None:
q.filter('__key__ <', Namespace.key_for_namespace(end))
# Return list of query results
return [ns.namespace_name for ns in q]
종류 쿼리
종류 쿼리는 키 이름이 항목 종류의 이름인 __kind__
종류의 항목을 반환합니다. 이 유형의 쿼리는 현재 네임스페이스로만 암시적으로 제한되며 __key__
유사 속성을 범위로 하는 필터링만 지원합니다. 결과는 __key__
값의 오름차순으로 정렬할 수 있습니다(내림차순 불가). __kind__
항목에 속성이 없기 때문에 키 전용 및 키 전용이 아닌 쿼리가 모두 동일한 정보를 반환합니다.
종류 항목은 모델 클래스 google.appengine.ext.db.metadata.Kind
의 인스턴스입니다.
항목 키에서 계산된 문자열 속성 kind_name
은 해당하는 항목 종류의 이름을 반환합니다. 쿼리를 용이하게 하도록 Kind
모델은 다음과 같은 클래스 메서드를 제공합니다.
Kind.key_for_kind()
는 종류 이름에서__kind__
키를 빌드합니다.Kind.key_to_kind()
는 지정된__kind__
키에 해당하는 종류 이름을 반환합니다.
예를 들어 다음은 도우미 함수 get_kinds()
의 구현입니다. 이 함수는 모든 애플리케이션 항목 종류의 이름(또는 지정한 이름 두 개(start
와 end
) 사이의 범위에 있는 이름)이 포함된 목록을 반환합니다.
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
def get_kinds(start=None, end=None):
# Start with unrestricted kind query
q = Kind.all()
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Kind.key_for_kind(start))
if end is not None:
if end == '':
return [] # Empty string is not a valid kind name, so can't filter
q.filter('__key__ <', Kind.key_for_kind(end))
# Return list of query results
return [k.kind_name for k in q]
다음 예시는 이름이 소문자로 시작하는 모든 종류를 표시합니다.
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
# Start with unrestricted kind query
q = Kind.all()
# Limit to lowercase initial letters
q.filter('__key__ >=', Kind.key_for_kind('a'))
endChar = chr(ord('z') + 1) # Character after 'z'
q.filter('__key__ <', Kind.key_for_kind(endChar))
# Print query results
for k in q:
print k.kind_name
속성 쿼리
속성 쿼리는 항목 종류와 연관된 속성을 나타내는 __property__
종류의 항목을 반환합니다(이 속성이 현재 이 종류의 모델에 정의되어 있는지 여부와 관계없이). K 종류의 P 속성을 나타내는 항목은 다음과 같이 빌드됩니다.
- 항목 키에는
__property__
종류 및 키 이름 P가 포함됩니다. - 상위 항목 키에는
__kind__
종류 및 키 이름 K가 포함됩니다.
속성 항목은 모델 클래스 google.appengine.ext.db.metadata.Property
의 인스턴스입니다. 문자열 속성 kind_name
과 property_name
은 해당 키에서 계산되고 해당 종류와 속성의 이름을 반환합니다. Property
모델은 __property__
키 빌드 및 검토를 단순화하는 4가지 클래스 메서드를 제공합니다.
Property.key_for_kind()
는 지정한 항목 종류의__property__
키에 대한 상위__kind__
키를 빌드합니다.Property.key_for_property()
는 지정된 종류 및 속성의__property__
키를 빌드합니다.Property.key_to_kind()
는__property__
키와 연관된 종류 이름을 반환합니다.Property.key_to_property()
는__property__
키와 연관된 속성 이름(또는 이 키가 종류 하나만 지정한 경우None
)을 반환합니다.
다음 예시는 이러한 메서드를 보여줍니다.
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
class Employee(db.Model):
name = db.StringProperty()
ssn = db.IntegerProperty()
employee_key = Property.key_for_kind("Employee")
employee_name_key = Property.key_for_property("Employee", "Name")
Property.key_to_kind(employee_key) # Returns "Employee"
Property.key_to_property(employee_name_key) # Returns "Name"
속성 쿼리의 동작은 아래 하위 섹션의 설명과 같이 키 전용 쿼리인지 또는 키 전용이 아닌(속성 표현) 쿼리인지에 따라 달라집니다.
속성 쿼리: 키 전용
키 전용 속성 쿼리는 지정된 항목 종류의 색인이 생성된 각 속성의 키를 반환합니다. (색인이 생성되지 않은 속성은 포함되지 않습니다.) 다음 예시에서는 애플리케이션의 모든 항목 종류와 각 항목과 연관된 속성의 이름을 보여줍니다.
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
# Create unrestricted keys-only property query
q = Property.all(keys_only=True)
# Print query results
for p in q:
print "%s: %s" % (Property.key_to_kind(p), Property.key_to_property(p))
이 유형의 쿼리는 현재 암시적으로 네임스페이스로 제한되고 유사 속성 __key__
범위의 필터링만 지원합니다. 여기서 키는 __kind__
또는 __property__
항목을 나타냅니다. 결과는 __key__
값의 오름차순으로 정렬할 수 있습니다(내림차순 불가). 필터링은 종류-속성 쌍에 적용되며, 처음에는 종류에 따라 그리고 두 번째는 속성에 따라 정렬됩니다. 예를 들어 다음과 같은 속성을 가진 항목이 있다고 가정합니다.
- 다음 속성이 있는
Account
종류balance
company
- 다음 속성이 있는
Employee
종류name
ssn
- 다음 속성이 있는
Invoice
종류date
amount
- 다음 속성이 있는
Manager
종류name
title
- 다음 속성이 있는
Product
종류description
price
속성 데이터를 반환하는 쿼리는 다음과 같습니다.
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
# Start with unrestricted keys-only property query
q = Property.all(keys_only=True)
# Limit range
q.filter('__key__ >=', Property.key_for_property("Employee", "salary"))
q.filter('__key__ <=', Property.key_for_property("Manager", "salary"))
# Print query results
for p in q:
print "%s: %s" % (Property.key_to_kind(p), Property.key_to_property(p))
위 쿼리는 다음을 반환합니다.
Employee: ssn
Invoice: date
Invoice: amount
Manager: name
결과에는 Employee
종류의 name
속성과 Manager
종류의 title
속성, Account
및 Product
종류의 속성이 포함되지 않습니다. 이러한 속성은 쿼리에 지정된 범위 밖에 있기 때문입니다.
속성 쿼리는 __kind__
또는 __property__
키에서 상위 필터링도 지원하여 단일 종류 또는 속성으로 쿼리 결과를 제한합니다. 다음 예시와 같이 이 점을 사용하여, 예를 들면 지정된 항목 종류와 연관된 속성을 가져올 수 있습니다.
get_properties_of_kind()
의 구현)
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
def get_properties_of_kind(kind, start=None, end=None):
# Start with unrestricted keys-only property query
q = Property.all(keys_only=True)
# Limit to specified kind
q.ancestor(Property.key_for_kind(kind))
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Property.key_for_property(kind, start))
if end is not None:
if end == '':
return [] # Empty string is not a valid property name, so can't filter
q.filter('__key__ <', Property.key_for_property(kind, end))
# Return list of query results
return [Property.key_to_property(p) for p in q]
속성 쿼리: 키 전용이 아닌 쿼리(속성 표현)
키 전용이 아닌 속성 쿼리(속성 표현 쿼리라고 함)는 각 종류-속성 쌍에 사용된 표현에 대한 추가 정보를 반환합니다. (색인이 생성되지 않은 속성은 포함되지 않습니다.) K 종류의 P 속성에 반환된 항목에는 속성의 표현을 반환하는 추가 property_representation
속성과 함께 해당 키 전용 쿼리와 동일한 키가 포함됩니다. 이 속성 값은 K 종류의 항목에서 발견된 P 속성의 각 표현에 대한 문자열 하나를 포함하는 StringListProperty
클래스의 인스턴스입니다.
표현은 속성 클래스와 동일하지 않으며 여러 속성 클래스가 동일 표현에 매핑될 수 있습니다. 예를 들어 StringProperty
및 PhoneNumberProperty
모두 STRING
표현을 사용합니다.
다음 표는 속성 클래스와 해당 표현을 보여줍니다.
속성 클래스 | 표현 |
---|---|
IntegerProperty |
INT64 |
FloatProperty |
DOUBLE |
BooleanProperty |
BOOLEAN |
StringProperty |
STRING |
ByteStringProperty |
STRING |
DateProperty |
INT64 |
TimeProperty |
INT64 |
DateTimeProperty |
INT64 |
GeoPtProperty |
POINT |
PostalAddressProperty |
STRING |
PhoneNumberProperty |
STRING |
EmailProperty |
STRING |
UserProperty |
USER |
IMProperty |
STRING |
LinkProperty |
STRING |
CategoryProperty |
STRING |
RatingProperty |
INT64 |
ReferenceProperty SelfReferenceProperty |
REFERENCE |
blobstore.BlobReferenceProperty |
STRING |
ListProperty |
목록 요소의 표현 |
StringListProperty |
목록 요소의 표현 |
예를 들어 다음은 도우미 함수 get_representations_of_kind()
의 구현입니다. 이 함수는 지정한 항목 종류와 관련된 색인이 생성된 모든 애플리케이션 속성의 표현(또는 지정한 이름 두 개(start
와 end
) 사이의 범위에 있는 표현)이 포함된 사전을 반환합니다. 이 사전은 각 속성의 이름을 해당 속성의 표현으로 이루어진 목록에 매핑합니다.
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
def get_representations_of_kind(kind, start=None, end=None):
# Start with unrestricted non-keys-only property query
q = Property.all()
# Limit to specified kind
q.ancestor(Property.key_for_kind(kind))
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Property.key_for_property(kind, start))
if end is not None:
if end == '':
return [] # Empty string is not a valid property name, so can't filter
q.filter('__key__ <', Property.key_for_property(kind, end))
# Initialize result dictionary
result = {}
# Add query results to dictionary
for p in q:
result[p.property_name] = p.property_representation
# Return dictionary
return result