오늘도 더 나은 코드를 작성하였습니까?

Realm kotlin scheme 본문

kotlin Multiplatform/realm-kotlin-kmm

Realm kotlin scheme

hik14 2022. 7. 25. 16:01

Timestamps

- Realm 데이터베이스에 Kotlin의 bulit-in date 또는 instance type을 저장할 수 없다. 

- 대신 시간 정보를 UNIX epoch 타임스탬프로 저장하는 RealmInstant 유형을 사용

 

RealmInstant가 아닌 다른 형식의 timestampes 데이터가 필요한 경우 다음 예제를 기반으로 모델 클래스에 변환 코드를 추가할 수 있습니다.

//Instant(kotlinx-datetime) 필드를 변환을 통해 RealmInstant로 저장하는 모델 클래스
class RealmInstantConversion: RealmObject {
    private var _timestamp: RealmInstant = RealmInstant.from(0, 0)
    public var timestamp: Instant
        get()
        { return _timestamp.toInstant() }
        set(value) {
            _timestamp = value.toRealmInstant()
        }
}


fun RealmInstant.toInstant(): Instant {
    val sec: Long = this.epochSeconds
     
    // 값은 항상 `-999_999_999..999_999_999` 범위에 있습니다.
    // Epoch 이전 타임스탬프의 경우 마이너스, 이후의 경우 양수
    val nano: Int = this.nanosecondsOfSecond
    
    return if (sec >= 0) { 
        // 양수 타임스탬프의 경우 직접변환
        Instant.fromEpochSeconds(sec, nano.toLong())
    }
    else {
        // 음수 타임스탬프의 경우 RealmInstant는 음수를 사용하여 더 높은 값부터 시작합니다.
        // 나노초, Instant는 양의 나노초로 낮은 값부터 시작합니다.
        // TODO 이것은 아마도 MIN/MAX와 같은 엣지 케이스에서 중단될 것입니다.
        Instant.fromEpochSeconds(sec - 1, 1_000_000 + nano.toLong())
    }
}

fun Instant.toRealmInstant(): RealmInstant {
    val sec: Long = this.epochSeconds
    // The value is always positive and lies in the range `0..999_999_999`.
    val nano: Int = this.nanosecondsOfSecond
    return if (sec >= 0) { // For positive timestamps, conversion can happen directly
        RealmInstant.from(sec, nano)
    }
    else {
        // For negative timestamps, RealmInstant starts from the higher value with negative
        // nanoseconds, while Instant starts from the lower value with positive nanoseconds
        // TODO This probably breaks at edge cases like MIN/MAX
        RealmInstant.from(sec + 1, -1_000_000 + nano)
    }
}

Ignore a Field

Field를 Realm 데이터베이스에서 삭제하거나  Realm 스키마에 표시되지 않도록 하려면 @Ignore 주석을 사용.

class ShoppingCart: RealmObject {
    val _id: ObjectId = ObjectId.create()
    @Ignore
    val items: List<String> = listOf()
}

Index a Field 

index는 일부 쿼리의 속도를 높이지만 삽입 및 업데이트 속도를 늦춥니다.

realm 데이터베이스는 디스크에 인덱스를 저장하므로 realm 파일이 더 커집니다.

필드를 인덱싱하려면 @Index 주석을 사용

 

class Movie: RealmObject {
    @Index
    val _id: ObjectId = ObjectId.create()
    val starring: List<String> = listOf()
}

인덱스는 Realm 데이터베이스에서 효율적인 쿼리 실행을 지원합니다. 

인덱스가 없으면 Realm 데이터베이스는 collection scan을 수행해야 합니다.

 

즉, 컬렉션의 모든 문서를 스캔하여 쿼리와 일치하는 문서를 선택해야 합니다.

쿼리에 적절한 인덱스가 있으면 Realm 데이터베이스는 인덱스를 사용하여 검사해야 하는 문서의 수를 제한할 수 있습니다.

 

Index는 탐색하기 쉬운 형식으로 Realm 데이터의 작은 부분을 저장하는 특수 데이터 구조입니다.

인덱스는 field 값으로 정렬된 특정 field의 값을 저장합니다.

인덱스 항목의 순서는 효율적인 동등 일치 및 범위 기반 쿼리 작업을 지원합니다.

 

  • String
  • Byte
  • Short
  • Int
  • Long
  • Boolean
  • RealmInstant
  • ObjectId

Optional Fields - Kotlin SDK

필드를 선택 사항으로 표시하려면 Default kotlin ? 코틀린 연산자를 이용한다.
 
class Knight: RealmObject {
    val _id: ObjectId = ObjectId.create()
    val name: String = ""
    val mount: Horse? = null
}

Primary Keys - Kotlin SDK

@PrimaryKey 주석으로 객체 유형에 대한 기본 키를 정의합니다.

class Lizard: RealmObject {
    @PrimaryKey
    val _id: ObjectId = ObjectId.create()
}
 
Realm 데이터베이스는 @PrimaryKey 주석으로 표시된 필드를 해당 객체 스키마의 기본 키로 처리합니다.
기본 키에는 다음 제한 사항이 적용됩니다.

개체 스키마당 하나의 기본 키만 정의할 수 있습니다.

기본 키 값은 영역에 있는 개체의 모든 인스턴스에서 고유해야 합니다.

- 중복된 기본 키 값을 삽입하려고 하면 오류가 발생합니다. 기본 키 값은 변경할 수 없습니다
- 개체의 기본 키 값을 변경하려면 원래 개체를 삭제하고 기본 키 값이 다른 새 개체를 삽입해야 합니다.
- Realm에 해당 유형의 객체를 추가한 후에는 객체 유형에 대한 기본 키 필드를 변경할 수 없습니다.
optional 필드는 기본 키 값으로 null 값을 포함할 수 있지만 각 기본 키 값은 고유해야 하므로 특정 유형의 하나의 개체에만 해당합니다.
기존 기본 키가 있는 개체를 영역에 삽입하려고 하면 오류가 발생합니다.
 
Realm 데이터베이스는 기본 키 필드를 자동으로 인덱싱하므로 기본 키를 기반으로 객체를 효율적으로 읽고 수정할 수 있습니다.

Relationships - Kotlin SDK

realtionship은  다른 Realm 객체를 참조하는 객체 property입니다.

 

관계는 Realm 의 다른 객체에 대한 직접 참조입니다.

즉, 관계형 데이터베이스에서처럼 관계를 정의하기 위해 브리지 테이블이나 명시적 조인이 필요하지 않습니다.

관계를 정의하는 속성을 읽고 쓰는 방식으로 관련 개체에 액세스할 수 있습니다.

Realm 데이터베이스는 읽기 작업을 느리게 실행하므로 관계 필드가 있는 객체를 쿼리해도 쿼리 속도가 느려지지 않습니다.

 

* Realm 데이터베이스에서는 동일한 file의 realm 내의 다른 개체에서 개체 참조를 제한할 수 있는 방법이 없습니다

결과적으로 "다대일/다대다"가 아닌 "일대일/일대다"로 관계를 제한할 수 있는 방법이 없습니다.

 

 

다음 유형을 사용하여 객체 스키마에서 관계를 정의할 수 있습니다.

 

  • RealmObject
  • RealmList <? extends RealmObject>

To-One Relationship

 

일대일 관계는 객체가 하나 이상의 다른 객체와 관련되어 있지 않음을 의미합니다.

relation field를 null로 설정하면 객체 간의 연결이 제거되지만 Realm 데이터베이스는 참조된 객체를 삭제하지 않습니다.

 

N : 1 또는 1:1 관계를 설정하려면 애플리케이션에서 유형이 Realm 객체인 필드를 생성

class SushiPlatter: RealmObject {
    val _id: ObjectId = ObjectId.create()
    val name: String = ""
    val fish: Fish? = null
}

To-Many Relationship

대다 관계는 개체가 특정 방식으로 여러 개체와 관련되어 있음을 의미합니다.

RealmList<?> 유형의 필드를 사용하여 하나의 객체와 여러 객체 사이의 관계를 만들 수 있습니다. 여기서 T는 애플리케이션의 Realm 객체입니다.

class Sushi: RealmObject {
    val _id: ObjectId = ObjectId.create()
    val name: String = ""
    val fishes: RealmList<Fish> = realmListOf<Fish>()
}

RealmList는 RealmObject의 컨테이너이지만 그렇지 않으면 일반 컬렉션처럼 작동합니다.

동일한 개체가 다대다 관계에서 발생할 수 있습니다.

다대다 관계와 일대다 관계의 구분은 애플리케이션에 달려 있습니다.

'kotlin Multiplatform > realm-kotlin-kmm' 카테고리의 다른 글

Realm Kotlin Create  (0) 2022.07.25
Realm Transaction  (0) 2022.07.25
Realm kotlin schem(Data Type)  (0) 2022.07.25
Frozen Architecture - Kotlin SDK  (0) 2022.07.25
Realm (Kotlin)  (0) 2022.07.22