Docs Menu
Docs Home
/ /
Atlas Device SDK
/ / /

CRUD - 읽기 - Flutter SDK

이 페이지의 내용

  • 특성 읽기
  • 결과가 사본이 아님
  • 결과 지연
  • 참조 유지됨
  • 쿼리 결과 제한
  • 페이지 매김
  • 객체 읽기
  • 기본 키로 객체 찾기
  • 모든 객체 쿼리
  • 관련 객체 쿼리
  • 쿼리 목록
  • 혼합 데이터의 중첩 컬렉션 쿼리
  • 목록 또는 세트를 결과로 변환
  • 결과 필터링
  • Full Text Search로 필터링하기
  • 결과 정렬
  • 결과 제한

객체를 찾고, 필터링하고, 정렬하여 데이터베이스에 저장한 데이터를 다시 읽을 수 있습니다.

데이터베이스 읽기는 일반적으로 다음 단계로 구성됩니다.

  • 데이터베이스에서 특정 유형의 모든 객체를 가져옵니다.

  • 선택적으로 결과를 필터링합니다.

쿼리 작업은 결과 컬렉션 를 반환합니다. . 이러한 컬렉션은 실시간이므로 항상 관련 쿼리 의 최신 결과가 포함되어 있습니다.

최대한 효율적으로 데이터를 읽을 수 있도록 이 세 가지 주요 읽기 특성을 중심으로 앱의 데이터 액세스 패턴을 설계하세요.

쿼리에 대한 결과는 데이터의 복사본이 아닙니다. 쿼리 결과를 수정하면 디스크의 데이터가 직접 수정됩니다. 또한 이 메모리 매핑은 결과가 실시간 즉, 항상 디스크의 현재 상태를 반영한다는 의미이기도 합니다.

SDK는 사용자가 실제로 해당 쿼리의 결과를 요청할 때만 쿼리를 실행합니다. 이 지연 평가를 사용하면 대규모 데이터 세트와 복잡한 쿼리를 처리할 수 있는 고성능 코드를 작성할 수 있습니다. 중간 상태를 처리하기 위한 추가 작업 없이 여러 필터 작업을 연결할 수 있습니다.

SDK 객체 모델의 한 가지 이점은 SDK가 자동으로 모든 객체의 관계 를 직접 참고로 유지한다는 것입니다. 이를 통해 쿼리 결과를 통해 관계 그래프를 직접 탐색할 수 있습니다.

직접 참조(포인터)를 사용하면 참조를 통해 관련 객체의 속성에 직접 액세스할 수 있습니다.

다른 데이터베이스는 직접 작업해야 할 때 일반적으로 데이터베이스 저장소의 객체를 애플리케이션 메모리로 복사합니다. 애플리케이션 객체에는 직접 참조가 포함되어 있으므로 각 직접 참조가 참조하는 객체가 필요할 경우 데이터베이스에서 객체를 복사하거나 각 객체에 대한 외래 키를 복사하고 해당 키에 액세스할 경우 해당 객체를 쿼리할 수 있습니다. 참조된 객체를 애플리케이션 메모리에 복사하면 액세스하지 않는 객체에 많은 리소스가 사용될 수 있는 반면 외래 키만 복사하도록 선택하면 참조된 객체 조회로 인해 애플리케이션 속도가 느려질 수 있습니다.

SDK는 제로 카피 라이브 객체를 사용하여 이 모든 과정을 우회합니다. SDK의 객체 접근자는 메모리 매핑을 사용하여 데이터베이스 스토리지를 직접 점하므로 데이터베이스의 객체와 애플리케이션 메모리의 쿼리 결과를 구분하지 않습니다. 이로 인해 쿼리 결과에서 전체 데이터베이스에 걸쳐 직접 참고를 순회할 수 있습니다.

평가가 지연되므로 SDK를 사용하여 쿼리 결과를 제한하기 위한 특별한 메커니즘이 필요하지 않습니다. 예를 들어, 쿼리가 수천 개의 객체와 일치하지만 처음 10개만 로드하려는 경우, 결과 collection의 처음 10개 요소에만 액세스하면 됩니다.

지연 평가 덕분에 일반적인 페이지 매김 작업이 아주 간단해집니다. 예를 들어, 데이터베이스의 수천 개의 객체와 일치하는 쿼리와 연결된 결과 collection이 있다고 가정해 보겠습니다. 페이지당 100개의 객체를 표시합니다. 원하는 페이지로 이동하려면 대상 페이지에 해당하는 인덱스부터 결과 collection의 요소에 액세스하기만 하면 됩니다.

달리 명시되지 않는 한 이 페이지의 예제에서는 PersonTeam 의 두 가지 Realm 객체 유형을 사용합니다.

@RealmModel()
class _Person {
@PrimaryKey()
late ObjectId id;
late String name;
late List<String> hobbies;
}
@RealmModel()
class _Team {
@PrimaryKey()
late ObjectId id;
late String name;
late List<_Person> crew;
late RealmValue eventLog;
}

Realm.find()를사용하여 프라이머리 키로 객체를 찾습니다.

final luke = realm.find<Person>(lukePrimaryKey);

Realm.all() 메서드 를 사용하여 데이터베이스에 있는 데이터 모델의 모든 객체 컬렉션을 메서드.

final people = realm.all<Person>();

버전 1.8.0에 추가 되었습니다.

데이터 모델에 다른 객체를 참조하는 객체가 포함된 경우 getBacklinks () 메서드.

이 메서드는 결과 컬렉션 을 반환합니다. to-one, to-many 또는 역관계를 통해 지정된 객체에 연결되는 모든 객체의 입니다. 다음 예제에서는 관계 페이지에 정의된 모델을 사용합니다.

  • 대일 관계: 이 예제에서는 Person 객체와 대일 관계를 가진 Bike 객체 모델이 있습니다.

    getBacklinks() 메서드를 사용하여 owner 속성을 통해 지정된 사람에 연결되는 Bike 객체를 찾습니다.

    // Persons have a to-one relationship with Bikes
    final person = realm.query<Person>("firstName == 'Anakin'").first;
    // Find all Bikes owned by a Person named 'Anakin'
    final allBikes = person.getBacklinks<Bike>('owner');
  • 대다 관계: 이 예제에서는 ScooterShop 객체와 대다 관계를 가진 Scooter 객체 모델이 있습니다.

    getBacklinks() 메서드를 사용하여 scooters 목록 속성을 통해 지정된 스쿠터에 연결된 ScooterShops 객체를 찾습니다.

    // Scooters have a to-many relationship with ScooterShops
    final scooters = realm.query<Scooter>("name == 'Scooterbug'").first;
    // Find all ScooterShops with a Scooter named 'Scooterbug'
    final shops = scooters.getBacklinks<ScooterShop>('scooters');
  • 역관계: 이 예제에서는 User 객체와 역관계를 갖는 Task 객체 모델이 있습니다.

    getBacklinks() 메서드를 사용하여 tasks 역링크 속성을 통해 지정된 작업에 연결되는 User 객체를 찾습니다.

    // Tasks have an inverse relationship to Users
    final inCompleteTasks = realm.query<Task>("isComplete == false");
    // Find all Users who have an incomplete Task
    for (final task in inCompleteTasks) {
    final ownersWithIncompleteTasks = task.getBacklinks<User>('tasks');
    for (final user in ownersWithIncompleteTasks) {
    print("User ${user.username} has incomplete tasks.");
    }
    }

모든 RealmObject 목록을 쿼리할 수 있습니다. 또는 기본 요소.

final config = Configuration.local([Person.schema, Team.schema]);
final realm = Realm(config);
final heroes = Team(ObjectId(), 'Millenium Falcon Crew', crew: [
Person(ObjectId(), 'Luke'),
Person(ObjectId(), 'Leia'),
Person(ObjectId(), 'Han'),
Person(ObjectId(), 'Chewbacca')
]);
realm.write(() => realm.add(heroes));
final lukeAndLeia = heroes.crew.query('name BEGINSWITH \$0', ['L']);

버전 2.0.0에 추가 되었습니다.

Flutter SDK v2.0.0 이상에서는 RealmValue 속성에 혼합 데이터의 컬렉션(목록 또는 맵)이 포함될 수 있습니다. 이러한 컬렉션은 컬렉션 내에 중첩될 수 있으며 혼합 데이터의 다른 컬렉션을 포함할 수 있습니다.

일반 목록 또는 사전 컬렉션 과 동일한 구문을 사용하여 쿼리 할 수 있습니다. 다음을 참조하세요. 지원되는 연산자 및 목록 비교에 대한 자세한 내용은 설명서를 참조하세요.

중첩된 컬렉션의 경우 다음을 사용할 수도 있습니다.

  • 대괄호 표기법은 다음과 같은 컬렉션 쿼리 연산자를 제공합니다.

    • [FIRST] 및 [LAST]: 컬렉션 내의 첫 번째 또는 마지막 요소와 일치합니다.

    • [<int>]: 특정 인덱스의 요소와 일치합니다.

    • [*]: 컬렉션 내의 모든 요소와 일치합니다(이 연산자는 해당 경로에서 컬렉션 유형을 가정).

    • [SIZE]: 컬렉션 길이와 일치합니다.

  • 다음 값을 지원하는 @type 연산자:

    • arraylist: 목록 컬렉션과 일치합니다.

    • dictionaryobject: 지도 컬렉션과 일치합니다.

    • collection: 목록 또는 지도 컬렉션과 일치합니다.

realm.write(() {
realm.addAll([
(Team(ObjectId(), 'Janitorial Staff',
eventLog: RealmValue.from({
'1': {
'date': DateTime.utc(5622, 8, 18, 12, 30, 0),
'type': ['work_order', 'maintenance'],
'summary': 'leaking pipes in control room',
'priority': 'high',
},
'2': {
'date': DateTime.utc(5622, 9, 18, 12, 30, 0),
'type': ['maintenance'],
'summary': 'trash compactor jammed',
'priority': 'low',
'comment': 'this is the second time this week'
}
}))),
(Team(ObjectId(), 'IT',
eventLog: RealmValue.from({
'1': {
'date': DateTime.utc(5622, 9, 20, 12, 30, 0),
'type': ['hardware', 'repair'],
'summary': 'lightsaber damage to server room',
'priority': 'high',
}
})))
]);
final teams = realm.all<Team>();
// Use bracket notation to query collection values at the specified path
final teamsWithHighPriorityEvents =
// Check any element at that path with [*]
teams.query("eventLog[*].priority == 'high'");
print(teamsWithHighPriorityEvents.length); // prints `2`
final teamsWithMaintenanceEvents =
// Check for the first element at that path with [FIRST]
teams.query("eventLog[*].type[FIRST] == 'maintenance'");
print(teamsWithMaintenanceEvents.length); // prints `1`
final teamsWithMultipleEvents =
// Check for collection at that path with matching elements
// Note that the order must match unless you use ANY or ALL
teams.query("eventLog[*].type[*] == {'maintenance', 'work_order'}");
print(
teamsWithMultipleEvents.length); // prints `0` because order matters
final teamsWithEventsAsLists =
// Check the collection type with @type
teams.query("eventLog[*].type.@type == 'list'");
print(teamsWithEventsAsLists.length); // prints `2`
});

해당 메서드를 사용하여 RealmList 또는 RealmSet 를 인스턴스로 변환할 수 있습니다.RealmResults

이러한 메서드는 기본 값뿐만 아니라 RealmObjects 의 목록과 세트를 지원합니다.

final config = Configuration.local([Person.schema, Team.schema]);
final realm = Realm(config);
final heroes = Team(ObjectId(), 'Millenium Falcon Crew', crew: [
Person(ObjectId(), 'Luke', hobbies: [
'Going to Tashi Station',
'Fixing the Moisture Vaporators'
]),
Person(ObjectId(), 'Leia', hobbies: [
'Going on diplomatic missions',
'Rescuing short stormtroopers'
]),
Person(ObjectId(), 'Han',
hobbies: ['Shooting first', 'Making fast Kessel Runs']),
Person(ObjectId(), 'Chewbacca', hobbies: [
'Fixing the Millenium Falcon',
'Tearing the arms off of droids'
])
]);
realm.write(() => realm.add(heroes));
// Converts the Team object's 'crew' List into a RealmResults<Person>.
final heroesCrewAsResults = heroes.crew.asResults();
final luke = heroesCrewAsResults.query("name == 'Luke'").first;
// Converts Luke's 'hobbies' list into a RealmResults<String>
final lukeHobbiesAsResults = luke.hobbies.asResults();

Realm.query() 메서드 RealmList 를 사용하여 객체의 특정 세그먼트를 검색하기 위해 를 필터링합니다. 메서드. query() 메서드의 인수에서 RQL을 사용하여 필터링을 수행합니다. RQL은 데이터베이스에서 객체를 검색하는 데 사용할 수 있는 문자열 기반 쿼리 언어입니다.

final team =
realm.query<Team>('name == \$0', ['Millennium Falcon Crew']).first;
final humanCrewMembers = team.crew.query('name != \$0', ['Chewbacca']);

필터에 반복 가능한 인수를 사용할 수 있습니다. 예를 들면 다음과 같습니다.

final listOfNames = ['Luke', 'Leia'];
final matchingRealmObjects =
realm.query<Person>('name IN \$0', [listOfNames]);

@links.<Type>.<Property> 구문을 사용하여 역관계로 필터링할 수도 있습니다. 예를 들어, 필터는 이를 참고하는 User 객체의 속성을 기반으로 Task 객체를 일치시킬 수 있습니다.

// Filter Tasks through the User's backlink property
// using `@links.<ObjectType>.<PropertyName>` syntax
final jarjarsIncompleteTasks = realm.query<Task>(
"ALL @links.User.tasks.username == 'jarjar_binks' AND isComplete == false");
final tasksForHan =
realm.query<Task>("ALL @links.User.tasks.username == 'han'");

쿼리 구성에 대한 자세한 내용은 Realm 쿼리 언어 참조 문서를 확인하세요.

RealmQL(RealmQL)을 사용하여 검색 인덱스( Full Text Search 인덱스 ) 주석이 있는 속성을 쿼리할 수 있습니다. 이러한 속성을 쿼리하려면 쿼리에 TEXT 술어를 사용하세요.

단어 앞에 - 문자를 붙여서 해당 단어에 대한 결과를 제외시키세요. 그 예로 -sheep wool을(를) 검색하면 wool에 대한 모든 검색 결과가 포함되는 동시에, sheep이(가) 포함된 결과가 제외됩니다.

Flutter SDK 버전 1.6.0 이상에서는 단어 끝에 * 문자를 배치하여 접두사를 지정할 수 있습니다. 예를 들어 wo* 에는 woolwoven 에 대한 모든 검색 결과가 포함됩니다. Flutter SDK는 현재 접미사 검색을 지원하지 않습니다 .

다음 예에서는 Rug.patternRug.material 필드를 쿼리합니다.

// Find rugs with a chevron pattern
final chevronRugs = realm.query<Rug>("pattern TEXT \$0", ["chevron"]);
// Find rugs with a wool material but not sheep wool
final notSheepWoolRugs = realm.query<Rug>("material TEXT \$0", [" -sheep wool"]);
// Find rugs with a material starting with "co-"
final coRugs = realm.query<Rug>("material TEXT \$0", ["co*"]);

Full Text Search(FTS, 전체 텍스트 검색) 인덱스는 다음 작업을 지원합니다.

  • 부울은 관련성 검색이 아닌 단어 검색과 일치합니다.

  • 토큰은 발음 부호 및 대소문자를 구분하지 않습니다.

  • 토큰은 ASCII 및 Latin-1 Supplement(서양 언어)의 문자로만 구성될 수 있습니다.

  • 그 외의 모든 문자는 공백으로 간주됩니다. 하이픈(-)으로 분리된 단어들(예: full-text)은 토큰 2개로 나뉩니다.

FTS 인덱스의 기능에 대한 자세한 내용은 RealmIndexType에 대한 API 참조를 참조하세요.

query() 메서드의 인수에 RealmQL SORT() 연산자 를 사용하여 쿼리 결과를 정렬합니다.

RQL SORT() 절에는 매개변수화된 쿼리 를 사용할 수 없습니다. 대신 문자열 또는 문자열 보간을 사용합니다.

realm.write(() {
realm.addAll([
Person(ObjectId(), 'Luke'),
Person(ObjectId(), 'Leia'),
Person(ObjectId(), 'Han'),
Person(ObjectId(), 'Chewbacca')
]);
});
final alphabetizedPeople =
realm.query<Person>('TRUEPREDICATE SORT(name ASC)');
for (var person in alphabetizedPeople) {
print(person.name);
}
// prints 'Chewbacca', 'Han', 'Leia', 'Luke'

query() 메서드의 인수에 RQL LIMIT() 연산자 를 사용하여 쿼리 결과를 제한합니다.

RQL LIMIT() 절에는 매개변수화된 쿼리 를 사용할 수 없습니다. 대신 문자열 또는 문자열 보간을 사용합니다.

realm.write(() {
realm.addAll([
Person(ObjectId(), 'Luke'),
Person(ObjectId(), 'Luke'),
Person(ObjectId(), 'Luke'),
Person(ObjectId(), 'Luke')
]);
});
final limitedPeopleResults =
realm.query<Person>('name == \$0 LIMIT(2)', ['Luke']);
// prints `2`
print(limitedPeopleResults.length);

돌아가기

만들기