datastore를 사용해 보았을 때

소개



GAE/Go 1학년입니다. API 서버의 코드를 작성하는 중 빠진 것을
정리하려고 생각합니다.

이번에는 datastore입니다.
트랜잭션 기능의 사용법도 기억해 쾌적해져 온 요즘입니다.

※GAE/Go 전제의 쓰는 방법이 되어 버리는 것, 용서해 주세요.

string 속성은 기본적으로 1500byte까지만 저장할 수 있습니다.



올해 처음에 빠진 것이 이것이었습니다.
datastore에서는 struct가 그대로 schema가 되기 때문에, 어쩐지 string의 상한을 의식하지 않았던 것이 좋지 않았습니다.

다음은 문서입니다. (필자가 GAE/Go를 사용하고 있기 때문에 Go보다
Fields (except for []byte) are indexed by default. Strings longer than 1500 bytes cannot be indexed; fields used to store long strings should be tagged with "noindex". Similarly, ByteStrings longer than 1500 bytes cannot be indexed.

견적 출처: htps : // c ぉ d. 오, ぇ. 코 m / 아펜 기네 / 드 cs / 고 / 다타 s / 루후 렌세 # hdr-P 로페 치에 s

noindex 태그를 붙이면 저장할 수 있습니다.
설명문이나 블로그라든지, 장문을 DB에 보관 유지하고 싶을 때에는 필수군요.

GAE/Go만 IN구를 사용할 수 없다



여러 Key를 사용하여 Get 할 수는 있지만 특정 속성 값으로 SELECT * FROM TABLE WHERE Property IN (A, B, C) 같은 Query를 던질 수는 없습니다.
하지만 Java라고 할 수있는 것 같습니다.

Go 문서라면
Operator    Meaning
=   Equal to
<   Less than
<=  Less than or equal to
>   Greater than
>=  Greater than or equal to

견적 출처: htps : // c ぉ d. 오, ぇ. 코 m / 아펜 기네 / 도 cs / 고 / 타타 s 토레 / 쿠에 리에 s # 후 리 rs

하지만 Java이면
Operator    Meaning
EQUAL   Equal to
LESS_THAN   Less than
LESS_THAN_OR_EQUAL  Less than or equal to
GREATER_THAN    Greater than
GREATER_THAN_OR_EQUAL   Greater than or equal to
NOT_EQUAL   Not equal to
IN  Member of (equal to any of the values in a specified list)

견적 출처: htps : // c ぉ d. 오, ぇ. 코 m / 아펜 기네 / 도 cs / 그럼 ぁ / data s 토레 / 쿠에 리 s # 푹신 rs

되어 있고, IN이 있습니다

Transaction 기능을 사용하고 싶지 않습니다.



다음과 같은 코드를 작성했습니다.

type (
    SampleRepository struct {
        c context.Context
    }
    Sample struct {
        ID    int `datastore:"Id"`
        Count int `datastore:"Count"`
    }
)

func (r *SampleRepository) Save(sample *Sample) error {
    key := datastore.NewKey(r.c, "Sample", "", sample.ID, nil)
    if _, err := datastore.Put(ctx, key, sample); err != nil {
        return err
    }
    return nil
}

func handle(w http.ResponseWriter, r *http.Request) {
    ctx := appengine.NewContext(r)
    sr := SampleRepository{c: ctx}
    s := Sample{ID: 1}
    err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
        s.Count++
        return sr.Save(s)
    }, nil)
    if err != nil {
        //エラーレスポンスを返す
        return
    }
    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    fmt.Fprintf(w, "Count=%d", s.Count)
}
func(ctx context.Context) error 인수는 transaction을 포함하는 컨텍스트를 지정합니다.
transaction을 내장한 context가 아니면 트랜잭션은 당연히 효과가 없었습니다.
(참고: htps: //아이 c. 오 rg/오오 gぇ. 미안해. 오 rg / 아펜 기네 / r r l # 룬 T 란사 c 치오 노세 )

Repository 구조체를 만들 때 속성으로 context를 투입하도록 했기 때문에,
문제를 깨닫는 데 시간이 걸렸습니다.

결론



그 밖에도, schema 변경해 마이그레이션 하는 것이 힘들거나 , 라고 하는 고생도 있습니다만 , MySQL 때에 당연히 하고 있던 sharding 을 생각하지 않아도 좋아지거나 ,
칼럼 추가는 간단하거나, 좋은 곳도 가득 있구나, 라는 감상입니다.

아직 Ancestor Query를 사용할 수 없으므로 어딘가에서 도전하고 싶습니다.

좋은 웹페이지 즐겨찾기