항목 속성 참조

Datastore 모드의 Firestore(Datastore)는 다양한 속성 값 데이터 유형을 지원합니다. 여기에는 다음이 포함됩니다.

  • 정수
  • 부동 소수점 수
  • 문자열
  • 날짜
  • 바이너리 데이터

전체 유형 목록은 속성 및 값 유형을 참조하세요.

속성 및 값 유형

항목과 연관된 데이터 값은 하나 이상의 속성으로 구성됩니다. 각 속성에는 이름과 하나 이상의 값이 있습니다. 속성에는 둘 이상의 유형 값이 있을 수 있으며, 두 개의 항목에 동일한 속성의 서로 다른 유형 값이 있을 수 있습니다. 속성은 색인 생성되거나 색인 생성되지 않을 수 있으며, 속성 P를 기준으로 정렬 또는 필터링하는 쿼리는 P가 색인 생성되지 않은 항목을 무시합니다. 항목 하나에 포함될 수 있는 색인 생성된 속성은 최대 20,000개입니다.

다음 값 유형이 지원됩니다.

쿼리에 혼합 유형 값이 있는 필드가 있으면 Datastore는 내부 표시를 기준으로 확정된 순서를 사용합니다.

  1. Null 값
  2. 고정 소수점 수
    • 정수
    • 날짜 및 시간
  3. 부울 값
  4. 바이트 시퀀스
    • 유니코드 문자열
    • Blobstore 키
  5. 부동 소수점 수
  6. Datastore 키

long 텍스트 문자열 및 long 바이트 문자열은 색인이 생성되지 않기 때문에 순서가 정의되지 않습니다.

속성 유형

NDB에서는 다음과 같은 속성 유형이 지원됩니다.

속성 유형설명
IntegerProperty 부호 있는 64비트 정수
FloatProperty 배정밀도 부동 소수점 수
BooleanProperty 불리언
StringProperty 색인이 생성된 최대 1500바이트의 유니코드 문자열
TextProperty 색인이 생성되지 않은 무제한 길이의 유니코드 문자열
BlobProperty 해석되지 않은 바이트 문자열:
indexed=True를 설정한 경우 색인이 생성된 최대 1500바이트 문자열
indexedFalse인 경우(기본값) 색인이 생성되지 않은 무제한 길이 문자열
선택적 키워드 인수: compressed
DateTimeProperty 날짜 및 시간(날짜 및 시간 속성 참조)
DateProperty 날짜(날짜 및 시간 속성 참조)
TimeProperty 시간(날짜 및 시간 속성 참조)
GeoPtProperty 지리적 위치. ndb.GeoPt 객체입니다. 이 객체에는 모두 부동 소수점인 latlon 속성이 있습니다. ndb.GeoPt(52.37, 4.88)와 같은 부동 소수점 2개 또는 ndb.GeoPt("52.37, 4.88") 문자열을 사용하여 객체를 생성할 수 있습니다. 실제로는 db.GeoPt와 동일한 클래스입니다.
KeyProperty Datastore 키
선택적 키워드 인수: kind=kind. 이 속성에 할당된 키에는 항상 표시된 종류가 포함되어야 합니다. 문자열 또는 모델 서브클래스일 수 있습니다.
BlobKeyProperty Blobstore 키
이전 db API의 BlobReferenceProperty에 해당하지만 속성 값이 BlobInfo 대신 BlobKey입니다. BlobInfo(blobkey)를 사용하여 BlobInfo를 생성할 수 있습니다.
UserProperty 사용자 객체
StructuredProperty 값에 따라 다른 모델 내에서 한 종류의 모델을 포함합니다(구조화된 속성 참조).
LocalStructuredProperty StructuredProperty와 비슷하지만 디스크 상 표현이 불투명 blob이고 색인이 생성되지 않습니다(구조화된 속성 참조).
선택적 키워드 인수: compressed
JsonProperty 값은 Python의 json 모듈을 사용하여 직렬화할 수 있는 Python 객체(예: 목록, 사전 또는 문자열)입니다. Datastore는 JSON 직렬화를 blob으로 저장합니다. 기본적으로 색인이 생성되지 않습니다.
선택적 키워드 인수: compressed
PickleProperty 값은 Python pickle 프로토콜을 사용하여 직렬화할 수 있는 Python 객체(예: 목록, 사전 또는 문자열)입니다. Datastore는 pickle 직렬화를 blob으로 저장합니다. 기본적으로 색인이 생성되지 않습니다.
선택적 키워드 인수: compressed
GenericProperty 일반 값
대부분 Expando 클래스에서 사용되지만 명시적으로 사용할 수도 있습니다. 값 유형은 int, long, float, bool, str, unicode, datetime, Key, BlobKey, GeoPt, User, None일 수 있습니다.
ComputedProperty 맞춤 설정 함수에 의해 다른 속성에서 계산된 값입니다. (계산된 속성을 참조하세요.)

이러한 속성 중 일부에는 선택적 키워드 인수인 compressed가 포함됩니다. 속성에 compressed=True가 있으면 데이터는 디스크에서 gzip을 통해 압축됩니다. 소비 공간이 줄어들지만 쓰기 및 읽기 작업을 수행할 때 인코딩/디코딩을 위해 CPU가 필요합니다.

압축과 압축 해제는 모두 '지연' 작업입니다. 압축된 속성 값은 사용자가 이를 처음에 액세스할 때만 압축 해제됩니다. 압축된 속성 값을 포함하는 항목을 읽고, 압축된 속성에 액세스하지 않고 이를 다시 쓰면, 압축 해제와 압축이 전혀 수행되지 않습니다. 컨텍스트 내 캐시도 이러한 지연 방식을 따르지만, memcache는 항상 압축된 속성의 압축된 값을 저장합니다.

압축에 필요한 추가 CPU 시간 때문에, 일반적으로는 압축하지 않으면 데이터가 너무 큰 경우에만 압축된 속성을 사용하는 것이 가장 좋습니다. 이미지 및 기타 미디어 데이터의 경우는 일반적으로 gzip 기반 압축이 효율적이지 않습니다. 이러한 형식은 미디어별 압축 알고리즘(예: JPEG 이미지)을 사용하여 이미 압축되어 있기 때문입니다.

속성 옵션

대부분의 속성 유형에는 일부 표준 인수가 지원됩니다. 첫 번째는 속성의 Datastore 이름을 지정하는 선택적인 위치 인수입니다. 이를 사용하면 애플리케이션의 관점과 달리 Datastore에서 다른 이름을 속성에 지정할 수 있습니다. 예를 들어 코드에서는 더 길고 의미 있는 이름을 사용하더라도 Datastore가 축약된 속성 이름을 사용하도록 허용함으로써 Datastore에서 저장 공간을 줄일 수 있습니다. 예를 들면 다음과 같습니다.

class Employee(ndb.Model):
    full_name = ndb.StringProperty('n')
    retirement_age = ndb.IntegerProperty('r')

항목당 많은 값이 예상되는 반복된 속성의 경우 특히 유용합니다.

또한 대부분의 속성 유형에서는 다음과 같은 키워드 인수가 지원됩니다.

인수유형기본값 설명
indexed bool 일반적으로 True Datastore 색인에 속성을 포함시킵니다. False인 경우 값을 쿼리할 수 없지만, 쓰기가 더 빨라집니다. 모든 속성 유형에서 색인 생성이 지원되지는 않습니다. 이러한 유형에서 indexedTrue로 설정하면 실패합니다.
색인이 생성되지 않은 속성은 색인이 생성된 속성보다 쓰기 작업 비용이 낮습니다.
repeated bool False 속성 값은 기본 유형의 값을 포함하는 Python 목록입니다(반복 속성 참조).
required=True 또는 default=True와 함께 사용할 수 없습니다.
required bool False 속성에 값이 지정되어 있어야 합니다.
default 속성의 기본 유형없음 없음이 명시적으로 지정된 경우 속성의 기본값입니다.
choices 기본 유형의 값 목록None 허용 가능한 값의 선택적 목록입니다.
validator 함수None

값을 검증하고 선택적으로 강제할 수 있는 선택적인 함수입니다.

인수(prop, value)를 사용해서 호출되고 (선택적으로 강제된) 값을 반환하거나 예외를 일으킵니다. 강제된 값에서 함수를 다시 호출하면 값이 추가로 수정되지 않습니다. 예를 들어 value.strip() 또는 value.lower()를 반환할 수 있지만 value + '$'를 반환할 수 없습니다. 또한 '변경 없음'을 의미하는 None을 반환할 수 있습니다. 속성 서브클래스 쓰기도 참조하세요.

verbose_name 문자열None

jinja2와 같이 웹 양식 프레임워크에서 사용할 선택적인 HTML 레이블입니다.

반복 속성

repeated=True가 포함된 모든 속성은 반복 속성이 됩니다. 이 속성은 단일 값 대신 기본 유형의 값 목록을 사용합니다. 예를 들어 IntegerProperty(repeated=True)로 정의된 속성의 값은 정수 목록입니다.

Datastore는 이러한 속성에 대해 여러 값을 확인할 수 있습니다. 각 값에 대해 개별 색인 레코드가 생성됩니다. 이것은 쿼리 시맨틱스에 영향을 줍니다. 예시를 보려면 반복 속성 쿼리를 참조하세요.

이 예에는 반복 속성이 사용됩니다.

class Article(ndb.Model):
    title = ndb.StringProperty()
    stars = ndb.IntegerProperty()
    tags = ndb.StringProperty(repeated=True)
...
article = Article(
    title='Python versus Ruby',
    stars=3,
    tags=['python', 'ruby'])
article.put()

이렇게 하면 다음과 같은 내용의 Datastore 항목이 생성됩니다.

assert article.title == 'Python versus Ruby'
assert article.stars == 3
assert sorted(article.tags) == sorted(['python', 'ruby'])

tags 속성을 쿼리하면 이 항목은 'python' 또는 'ruby' 중 하나에 필요한 쿼리를 충족합니다.

반복 속성을 업데이트할 때는 이를 새 목록에 할당하거나 기존 목록을 변형시킬 수 있습니다. 새 목록을 할당할 때는 목록 항목의 유형이 즉시 검증됩니다. 잘못된 항목 유형(예: [1, 2]art.tags에 할당)은 예외를 발생시킵니다. 목록을 변형할 때는 변경사항이 즉시 검증되지 않습니다. 대신 사용자가 Datastore에 항목을 기록할 때 값이 검증됩니다.

Datastore에서는 반복되는 속성의 목록 항목 순서를 유지하므로 순서에 의미를 부여할 수 있습니다.

날짜 및 시간 속성

날짜 및 시간 관련 값을 정렬할 때는 세 가지 속성 유형을 사용할 수 있습니다.

  • DateProperty
  • TimeProperty
  • DateTimeProperty

이러한 속성 유형은 표준 Python datetime 모듈의 해당 클래스(date, time, datetime)에 속하는 값을 사용합니다. 세 가지 유형 중 가장 일반적인 유형인 DateTimeProperty는 달력 날짜 및 시간을 모두 나타냅니다. 다른 유형은 날짜만 필요한 경우(예: 생일) 또는 시간만 필요한 경우(예: 회의 시간)와 같은 특별한 목적에 유용할 수 있습니다. 기술적인 이유로 인해 DatePropertyTimePropertyDateTimeProperty의 서브클래스이지만 이러한 상속 관계에 의존해서는 안 됩니다. 이 관계는 datetime 모듈 자체로 정의된 기본 클래스 사이의 상속 관계와 다릅니다.

참고: App Engine 시간은 항상 UTC(협정 세계시)로 표시됩니다. 이는 현재 날짜 또는 시간(datetime.datetime.now())을 값으로 사용하거나 날짜/시간 객체 및 POSIX 타임스탬프 또는 시간 튜플 사이에서 변환할 경우 영향을 줍니다. 하지만 Datastore에는 명시적 시간대 정보가 저장되지 않으므로 주의해서 현재 시간 또는 변환을 사용하면 모든 시간대에서 지역 시간을 나타낼 수 있습니다.

이러한 각 속성에는 2개의 추가 부울 키워드 옵션이 포함되어 있습니다.

옵션설명
auto_now_add 항목이 생성될 때 현재 날짜/시간으로 속성을 설정합니다. 이 속성은 수동으로 재정의할 수 있습니다. 항목이 업데이트될 때는 속성이 변경되지 않습니다. 이 동작에는 auto_now를 사용합니다.
auto_now 항목이 생성될 때 그리고 업데이트될 때마다 현재 날짜/시간으로 속성을 설정합니다.

이러한 옵션은 repeated=True와 함께 사용할 수 없습니다. 두 가지 모두 기본값은 False입니다. 두 항목 모두 True로 설정된 경우 auto_now가 우선 적용됩니다. auto_now_add=True가 포함된 속성의 값을 재정의할 수 있지만 auto_now=True가 포함된 속성의 값을 재정의할 수 없습니다. 항목이 기록될 때까지 자동 값이 생성되지 않으므로, 이러한 옵션은 동적 기본값을 제공하지 않습니다. (이러한 세부정보는 이전 db API와 다릅니다.)

참고: auto_now_add=True가 포함된 속성을 작성하는 트랜잭션이 실패하고 나중에 재시도되면 트랜잭션을 재시도 시간으로 업데이트하는 대신 원래 트랜잭션과 동일한 시간 값을 재사용합니다. 트랜잭션이 영구적으로 실패해도 속성의 값이 항목의 메모리 내 사본에 설정됩니다.

구조화된 속성

모델의 속성을 구성할 수 있습니다. 예를 들어 각 내부 구조를 포함하여 주소 목록이 포함된 Contact 모델 클래스를 정의할 수 있습니다. 구조화된 속성(StructuredProperty 유형)을 사용하면 가능합니다. 예를 들면 다음과 같습니다.

class Address(ndb.Model):
    type = ndb.StringProperty()  # E.g., 'home', 'work'
    street = ndb.StringProperty()
    city = ndb.StringProperty()
...
class Contact(ndb.Model):
    name = ndb.StringProperty()
    addresses = ndb.StructuredProperty(Address, repeated=True)
...
guido = Contact(
    name='Guido',
    addresses=[
        Address(
            type='home',
            city='Amsterdam'),
        Address(
            type='work',
            street='Spear St',
            city='SF')])

guido.put()

이러면 다음과 같은 속성을 포함하는 단일 Datastore 항목이 생성됩니다.

assert guido.name == 'Guido'
addresses = guido.addresses
assert addresses[0].type == 'home'
assert addresses[1].type == 'work'
assert addresses[0].street is None
assert addresses[1].street == 'Spear St'
assert addresses[0].city == 'Amsterdam'
assert addresses[1].city == 'SF'

이러한 항목을 다시 읽으면 원래 Contact 항목이 정확하게 다시 구성됩니다. Address 인스턴스는 모델 클래스와 동일한 구문을 통해 정의되더라도 완전한 항목이 아닙니다. 이러한 항목은 Datastore에서 자신의 고유 키를 갖고 있지 않습니다. 이러한 항목은 자신이 속하는 Contact 항목과 별개로 검색될 수 없습니다. 하지만 애플리케이션은 자신의 개별 필드 값을 쿼리할 수 있습니다. 구조화된 속성 값 필터링을 참조하세요. address.type, address.street, address.city는 Datastore의 관점에서 병렬 배열로 보이지만 NDB 라이브러리는 이러한 관점을 숨기고 해당 Address 인스턴스 목록을 구성합니다.

구조화된 속성에는 일반적인 속성 옵션을 지정할 수 있습니다(indexed 제외). 이 경우에서 Datastore 이름은 두 번째 위치 인수입니다. 첫 번째는 하위 구조를 정의하는 데 사용되는 모델 클래스입니다.

하위 구조의 내부 속성을 쿼리할 필요가 없으면 로컬 구조화 속성(LocalStructuredProperty)을 대신 사용할 수 있습니다. 위 예시에서 StructuredPropertyLocalStructuredProperty로 바꾸면 Python 코드 동작은 동일하지만 Datastore는 주소마다 불투명한 blob만 확인합니다. 이 예시에서 생성된 guido 항목은 다음과 같이 저장됩니다. name = 'Guido' address = <opaque blob for {'type': 'home', 'city': 'Amsterdam'}> address = <opaque blob for {'type': 'work', 'city': 'SF', 'street': 'Spear St'}>

항목은 다시 올바르게 읽힙니다. 이 유형의 속성은 항상 색인이 생성되지 않기 때문에 주소 값을 쿼리할 수 없습니다.

참고: 중첩 속성(구조화 여부 관계없음)이 포함된 StructuredProperty는 반복 속성의 단일 레이어만 지원합니다. StructuredProperty를 반복하거나 중첩 속성을 반복할 수 있지만, 둘 다 반복할 수는 없습니다. 이러한 제약조건이 없는 LocalStructuredProperty를 사용하여 문제를 해결할 수 있지만, 이 경우 속성 값에 대한 쿼리가 허용되지 않습니다.

계산된 속성

계산된 속성(ComputedProperty)은 애플리케이션에서 제공된 함수로 다른 속성 값에서 값을 계산하는 읽기 전용 속성입니다. 계산된 속성은 일반 속성에서 지원되는 유형만 지원합니다. 계산된 값이 Datastore에 기록되어 Datastore 뷰어에서 값을 쿼리 및 표시할 수 있지만 Datastore에서 항목을 다시 읽을 때는 저장된 값이 무시됩니다. 대신 값이 요청될 때마다 함수를 호출하여 값을 다시 계산합니다. 예를 들면 다음과 같습니다.

class SomeEntity(ndb.Model):
    name = ndb.StringProperty()
    name_lower = ndb.ComputedProperty(lambda self: self.name.lower())
...
entity = SomeEntity(name='Nick')
entity.put()

다음 속성 값으로 항목을 저장합니다.

assert entity.name == 'Nick'
assert entity.name_lower == 'nick'

이름을 'Nickie'로 바꾸고 name_lower 값을 요청하면 'nickie'가 반환됩니다.

entity.name = 'Nick'
assert entity.name_lower == 'nick'
entity.name = 'Nickie'
assert entity.name_lower == 'nickie'

참고: 애플리케이션이 계산된 값을 쿼리할 경우 ComputedProperty를 사용하세요. Python 코드에서 파생된 버전만 사용하려면 일반 메서드를 정의하거나 Python의 기본 제공 @property를 사용하세요.

참고: 키를 수동으로 지정하지 않고 모델을 만들면서 대신 Datastore가 항목 ID를 자동 생성하도록 하면 ID가 생성되기 전에 필드가 계산되므로 첫 번째 put()에서 ComputedProperty가 ID 필드를 읽을 수 없습니다. 항목 ID를 사용하는 ComputedProperty가 필요한 경우 allocate_ids 메서드를 사용하여 ID와 키를 생성하고 이를 사용하여 항목을 만들면 됩니다. 그러면 ComputedProperty가 항목의 첫 번째 put()에서 ID를 참조할 수 있습니다.

Google 프로토콜 RPC 메시지 속성

Google 프로토콜 RPC 라이브러리는 구조화된 데이터에 Message 객체를 사용합니다. 이러한 객체는 RPC 요청, 응답 또는 기타 항목을 나타낼 수 있습니다. NDB는 Google 프로토콜 RPC Message객체를 항목 속성으로 저장하는 데 필요한 API를 제공합니다. Message 서브클래스를 정의한다고 가정해보겠습니다.

from protorpc import messages
...
class Note(messages.Message):
    text = messages.StringField(1, required=True)
    when = messages.IntegerField(2)

NDB msgprop API를 사용하여 Datastore에 Note 객체를 항목 속성 값으로 저장할 수 있습니다.

from google.appengine.ext import ndb
from google.appengine.ext.ndb import msgprop
...
class NoteStore(ndb.Model):
    note = msgprop.MessageProperty(Note, indexed_fields=['when'])
    name = ndb.StringProperty()
...
my_note = Note(text='Excellent note', when=50)

ns = NoteStore(note=my_note, name='excellent')
key = ns.put()

new_notes = NoteStore.query(NoteStore.note.when >= 10).fetch()

필드 이름을 쿼리하려면 색인이 생성되어 있어야 합니다. indexed_fields 매개변수를 사용하여 색인이 생성될 필드 이름 목록을 MessageProperty에 지정할 수 있습니다.

MessageProperty는 일부 옵션을 제외한 다양한 속성 옵션을 지원합니다. 지원되는 옵션은 다음과 같습니다.

  • name
  • repeated
  • required
  • default
  • choices
  • validator
  • verbose_name

메시지 속성은 indexed 속성 옵션을 지원하지 않으므로 Message 값에 색인을 생성할 수 없습니다. (메시지의 필드는 위에 설명된 대로 색인을 생성할 수 있습니다.)

중첩된 메시지(MessageField 사용)도 작동합니다.

class Notebook(messages.Message):
    notes = messages.MessageField(Note, 1, repeated=True)
...
class SignedStorableNotebook(ndb.Model):
    author = ndb.StringProperty()
    nb = msgprop.MessageProperty(
        Notebook, indexed_fields=['notes.text', 'notes.when'])

MessageProperty에는 특수 속성 옵션인 protocol이 있습니다. 이 옵션은 메시지 객체가 Datastore에 직렬화되는 방식을 지정합니다. 값은 protorpc.remote.Protocols 클래스에서 사용된 것처럼 프로토콜 이름입니다. 지원되는 프로토콜 이름은 protobufprotojson이고 기본값은 protobuf입니다.

msgpropEnumProperty도 정의합니다. 항목에 protorpc.messages.Enum 값을 저장하는 데 이 속성 유형을 사용할 수 있습니다. 예:

class Color(messages.Enum):
    RED = 620
    GREEN = 495
    BLUE = 450
...
class Part(ndb.Model):
    name = ndb.StringProperty()
    color = msgprop.EnumProperty(Color, required=True)
...
p1 = Part(name='foo', color=Color.RED)
print p1.color  # prints "RED"

EnumProperty는 값을 정수로 저장합니다. 실제로 EnumPropertyIntegerProperty의 서브클래스입니다. 즉, 이미 저장된 항목을 수정할 필요 없이 열거형 값의 이름을 바꿀 수 있지만, 번호는 다시 지정할 수 없습니다.

EnumProperty는 다음과 같은 속성 옵션을 지원합니다.

  • name
  • indexed
  • repeated
  • required
  • default
  • choices
  • validator
  • verbose_name

NDB 항목 모델 정보

NDB 항목 모델은 속성을 정의할 수 있습니다. 항목 속성은 데이터 저장을 위한 구조화된 방법인 Python 클래스의 데이터 멤버와 다소 비슷하지만, 데이터베이스 스키마의 필드와도 다소 비슷합니다.

일반적인 애플리케이션은 일부 속성 클래스 속성이 포함된 Model에서 상속되는 클래스를 정의하여 데이터 모델을 정의합니다. 예를 들면 다음과 같습니다.


from google.appengine.ext import ndb
...
class Account(ndb.Model):
    username = ndb.StringProperty()
    userid = ndb.IntegerProperty()
    email = ndb.StringProperty()

여기서 username, userid, emailAccount 속성입니다.

이것들은 몇 가지 다른 속성 유형입니다. 일부는 날짜 및 시간을 나타내기에 좋으며, 편리한 자동 업데이트 기능을 갖고 있습니다.

애플리케이션은 속성에 옵션을 지정하여 속성 동작을 조정할 수 있습니다. 이것들은 검증을 용이하게 해주고, 기본값을 설정하고, 쿼리 색인 생성을 변경할 수 있습니다.

모델은 보다 복잡한 속성을 포함할 수 있습니다. 반복 속성은 목록과 비슷합니다. 구조화된 속성은 객체와 비슷합니다. 읽기 전용 계산된 속성은 함수를 통해 정의되며, 하나 이상의 다른 속성에서 속성을 쉽게 정의할 수 있게 해줍니다. Expando 모델은 속성을 동적으로 정의할 수 있습니다.