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

CRUD - 読み取り - Flutter SDK

項目一覧

  • 読み取り特性
  • 結果はコピーではない
  • 結果は遅延
  • 参照は保持されます
  • クエリ結果の制限
  • ページ分割
  • オブジェクトの読み取り
  • プライマリキーによるオブジェクトの検索
  • すべてのオブジェクトのクエリ
  • クエリ関連オブジェクト
  • クエリ リスト
  • 混合データのネストされたコレクションのクエリ
  • リストまたはセットの結果への変換
  • 結果のフィルタリング
  • 全文検索でフィルタリング
  • 結果を並べ替える
  • 結果を制限する

オブジェクトを検索、フィルタリング、ソートすることで、 データベースに保存したデータを読み取ることができます。

データベースからの読み取りには通常、次の手順で構成されます。

  • データベースから特定の型のすべてのオブジェクトを取得します。

  • 必要に応じて、結果をフィルタリングします。

クエリ操作により の 結果コレクション が返されます 。これらのコレクションはライブです。つまり、関連付けられたクエリの最新の結果が常に含まれています。

これらの 3 つの主要な読み取り特性に関連するアプリのデータアクセス パターンを設計し、データをできるだけ効率的に読み取るようにします。

クエリの結果はデータのコピーではない クエリの結果を変更すると、ディスク上のデータが直接変更されます。 このメモリ マッピングは、結果がライブであることも意味します。つまり、ディスクの現在の状態を常に反映します。

SDK は、そのクエリの結果を実際に要求した場合にのみクエリを実行します。 この遅延評価により、大規模なデータセットや複雑なクエリを処理するための高パフォーマンスのコードを記述できます。 中間状態を処理するために追加の作業なしに、複数のフィルター操作を連鎖させることができます。

SDK のオブジェクトモデルの利点の 1 つは、SDK がオブジェクトのすべての関係を直接参照として自動的に保持することです。 これにより、クエリの結果から関係のグラフを直接走査できます。

直接参照(ポインター)を使用すると、参照を介して関連オブジェクトのプロパティに直接アクセスできます。

他のデータベースでは通常、オブジェクトを直接操作する必要がある場合、データベース ストレージからアプリケーション メモリにオブジェクトがコピーされます。 Because application objects contain direct references, you are left with a choice: copy the object referred to by each direct reference out of the database in case it's needed, or just copy the foreign key for each object and query for the object with that key if it's accessed. 参照されたオブジェクトをアプリケーション メモリにコピーすることを選択すると、アクセスされていないオブジェクトの多くのリソースを使用することができますが、外部キーのみをコピーすることを選択した場合は、参照されたオブジェクトの検索によってアプリケーションが遅くなる可能性があります。

SDK は、ゼロ コピーのライブ オブジェクトを使用して、これをすべてバイパスします。 SDK のオブジェクト アアクセスは、メモリ マッピングを使用してデータベース ストレージを直接指すため、データベース内のオブジェクトとアプリケーション メモリ内のクエリの結果を区別しません。 このため、どのクエリ結果からでもデータベース全体の直接参照を走査できます。

遅延評価の結果、SDK でクエリ結果を制限するために特別なメカニズムは必要ありません。 たとえば、クエリが数千のオブジェクトと一致するが、最初の 10 個のオブジェクトのみをロードする場合は、結果コレクションの最初の 10 個の要素のみにアクセスします。

遅延評価の代わりに、ページ区切りの一般的なタスクが非常に簡単になります。 たとえば、データベース内の数千のオブジェクトに一致するクエリに関連付けられた結果のコレクションがあるとします。 ページごとに 100 個のオブジェクトを表示します。 任意のページに進むには、ターゲット ページに対応するインデックスから、結果コレクションの要素にアクセスします。

特に指定がない限り、このページの例では PersonTeamの 2 つのオブジェクトタイプを使用します。

@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() メソッド を使用して 関係 をクエリできます 使用して複数のドキュメントを挿入できます。

このメソッドは 結果のコレクションを 返します 対 1、対多、または逆の関係で指定されたオブジェクトにリンクするすべてのオブジェクトの 。次の例では、関係ページで定義されたモデルを使用します。

  • 対 1 の関係:この例では、 Personオブジェクトと 1 の関係を持つ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 v 2.0.0以降では、 RealmValueプロパティに混合データのコレクション(リストまたはマップ)を含めることができます。 これらのコレクションはコレクション内にネストでき、混合データの他のコレクションを含めることができます。

これらは、通常のリストまたは辞書コレクションと同じ構文を使用してクエリできます。 を参照しますサポートされている演算子とリスト比較の詳細については、ドキュメントを参照してください。

ネストされたコレクションの場合は、次のコレクションも使用できます。

  • 括弧表記。次のコレクションクエリ演算子を提供します。

    • [FIRST] および [ LAST ]: コレクション内の最初または最後の要素と一致します。

    • [<int>]: 特定のインデックスの要素と一致する。

    • [*]: コレクション内の任意の要素と一致します(この演算子は、そのパスにあるコレクション タイプを想定しています)。

    • [SIZE]: コレクションの長さに一致します。

  • 次の値をサポートする@type演算子。

    • array およびlist : リスト コレクションに一致します。

    • dictionary およびobject : マップ コレクションに一致します。

    • 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またはRealmSetRealmResultsのインスタンスに変換できます。

これらのメソッドは、 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();

RealmListRealm.query() でオブジェクトの特定のセグメントを取得するには、 をフィルタリングします。使用して複数のドキュメントを挿入できます。 query() メソッドの引数では、 RQLを使用してフィルタリングを実行します。 RQLは、データベースからオブジェクトを検索するために使用できる string ベースのクエリ言語です。

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'");

クエリの構築の詳細については、 RQLに関する参考ドキュメント を参照してください。

RQL ( RQL )を使用して、全文検索インデックス(FTS)注釈を持つプロパティをクエリできます。 これらのプロパティをクエリするには、クエリでTEXT述語を使用します。

単語の前に-文字を付けて、単語の結果を除外します。 たとえば、 -sheep woolを検索すると、 sheepを持つ検索結果を除くwoolのすべての検索結果が含まれます。

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*"]);

全文検索(FTS)インデックスは以下をサポートします。

  • ブール値一致単語検索。関連性検索ではありません。

  • トークンは、発音区別符号を区別せず、大文字と小文字を区別しません。

  • トークンは、ASCII と Atlas 1 の追加文字(西部言語)のみで構成できます。

  • 他のすべての文字は空白と見なされます。 全文のようにハイフン(-)で区切られた単語は、2 つのトークンに分割されます。

FTS インデックスの機能の詳細については、 RealmIndexType の API リファレンスを参照してください。

query() メソッドの 引数でRQL SORT() 演算子を使用してクエリ結果を並べ替えます。

RQL SORT() 句では、パラメータ付きのクエリは使用できないことに注意してください。 代わりに、string または string 補間を使用してください。

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 ()演算子を使用してクエリ結果を制限します。

RQL LIT()句では、パラメータ付きのクエリは使用できないことに注意してください。 代わりに、string または string 補間を使用してください。

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);

戻る

作成