データのフィルタリング - Java SDK
項目一覧
クエリ エンジン
Realm 内のデータをフィルタリングするには、Realm クエリ エンジンを使用します。
Java SDK でクエリ エンジンにアクセスするには、次の 2 つの方法があります。
スムーズインターフェース
Java SDKは Flut インターフェース を使用します は、 クエリエンジンに渡される マルチ句クエリ を作成します。
RealmQuery API を参照 利用可能なメソッドの完全なリストについては、 を参照してください。
Realm コレクションをフィルタリングするために使用できる演算子にはいくつかのタイプがあります。 フィルターは、フィルタリングされるコレクション内のすべてのオブジェクトの演算子式を評価することで機能します。 式が true
に解決される場合、Realm Database は結果コレクションにオブジェクトを含めます。
式は、次のいずれかで構成されます。
現在評価されているオブジェクトのプロパティの名前。
演算子と最大 2 つの引数式(s)。
リテラルの string、数値、または日付。
このセクションの例について
このセクションの例では、タスク リスト アプリの単純なデータセットを使用します。 2 つの Realm オブジェクトタイプはProject
とTask
です。 Task
には、名前、割り当て者の名前、完了したフラグがあります。 また、優先順位(値が大きいほど重要)と、その作業に費やされた時間数もあります。 Project
には 0 個以上のTasks
があります。
これらの 2 つのクラス、 Project
とTask
のスキーマを以下で参照してください。
import org.bson.types.ObjectId; import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; import io.realm.annotations.RealmClass; import io.realm.annotations.Required; public class ProjectTask extends RealmObject { public ObjectId _id; public String name; public String assignee; public int progressMinutes; public boolean isComplete; public int priority; public String _partition; }
import org.bson.types.ObjectId; import io.realm.RealmList; import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; import io.realm.annotations.RealmClass; import io.realm.annotations.Required; public class Project extends RealmObject { public ObjectId _id; public String name; public RealmList<ProjectTask> tasks = new RealmList<>(); }
import io.realm.RealmObject import io.realm.annotations.PrimaryKey import io.realm.annotations.Required import org.bson.types.ObjectId open class ProjectTask( var _id: ObjectId = ObjectId(), var name: String = "", var assignee: String? = null, var progressMinutes: Int = 0, var isComplete: Boolean = false, var priority: Int = 0, var _partition: String = "" ): RealmObject()
import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.PrimaryKey import io.realm.annotations.Required import org.bson.types.ObjectId open class Project( var _id: ObjectId = ObjectId(), var name: String = "", var tasks: RealmList<ProjectTask> = RealmList(), ): RealmObject()
比較演算子
検索の最も簡単な操作は、値を比較することです。
演算子 | 説明 |
---|---|
between | 左側の数値式または日付式が右側の範囲と等しい場合、 true と評価されます。 日付の場合、左側の日付が右側の日付範囲内にある場合、これはtrue と評価されます。 |
equalTo | 左側の式が右側の式と等しい場合は、 true と評価されます。 |
greaterThan | 左側の数値または日付式が右側の数値または日付式より大きい場合は、 true と評価されます。 日付の場合、左側の日付が右側の日付より後の場合、これはtrue と評価されます。 |
greaterThanOrEqualTo | 左側の数値または日付式が右側の数値または日付式より大きい場合、 true と評価されます。 日付の場合、左側の日付が右側の日付より後のか同じである場合、これはtrue と評価されます。 |
in | 左側の式が右側のリストにある場合は、 true と評価されます。 |
lessThan | 左側の数値または日付式が右側の数値または日付式より小さい場合は、 true と評価されます。 日付の場合、左側の日付が右側の日付よりも前の場合、これはtrue と評価されます。 |
lessThanOrEqualTo | 左側の数値式が右側の数値式より小さい場合、 true と評価されます。 日付の場合、左側の日付が右側の日付よりも前の日付または同じ日付の場合、これはtrue と評価されます。 |
notEqualTo | 左側の式が右側の式と等しくない場合、 true と評価されます。 |
例
次の例では、クエリ エンジンの比較演算子を使用して次のようにします。
priority
プロパティ値の値をしきい値と比較して、優先順位の高いタスクを見つけます。どの優先順位を超えると、優先順位が高いと見なされます。progressMinutes
プロパティが特定の範囲内にあるかどうかを確認して、開始されたばかりのタスクまたは実行時間が短いタスクを見つけます。assignee
プロパティがnull
に等しいタスクを見つけて、割り当てられていないタスクを見つけます。assignee
プロパティが名前のリストにあるかどうかを確認して、特定のチームメイト エイリアスまたはレイテンシに割り当てられたタスクを見つけます。
RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class); Log.i("EXAMPLE", "High priority tasks: " + tasksQuery.greaterThan("priority", 5).count()); Log.i("EXAMPLE", "Just-started or short tasks: " + tasksQuery.between("progressMinutes", 1, 10).count()); Log.i("EXAMPLE", "Unassigned tasks: " + tasksQuery.isNull("assignee").count()); Log.i("EXAMPLE", "Ali or Jamie's tasks: " + tasksQuery.in("assignee", new String[]{"Ali", "Jamie"}).count());
val tasksQuery = realm.where(ProjectTask::class.java) Log.i("EXAMPLE", "High priority tasks: " + tasksQuery.greaterThan("priority", 5).count()) Log.i("EXAMPLE", "Just-started or short tasks: " + tasksQuery.between("progressMinutes", 1, 10).count()) Log.i("EXAMPLE", "Unassigned tasks: " + tasksQuery.isNull("assignee").count()) Log.i("EXAMPLE", "Ali or Jamie's tasks: " + tasksQuery.`in`("assignee", arrayOf("Ali", "Jamie")).count())
論理演算子
論理演算子を使用して複合述語を作成できます。
演算子 | 説明 |
---|---|
and | 左側の式と右側の式の両方が true である場合は、 true と評価されます。 |
not | 指定された式の結果を否定します。 |
or | いずれかの式が true を返す場合、 true と評価されます。 |
例
クエリ言語の論理演算子を使用して、Ali の完了したタスクをすべて検索できます。 つまり、 assignee
プロパティ値が 'Ali' に等しく、かつisComplete
プロパティ値がtrue
であるすべてのタスクを検索します。
RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class); Log.i("EXAMPLE", "Ali has completed " + tasksQuery.equalTo("assignee", "Ali").and().equalTo("isComplete", true).findAll().size() + " tasks.");
val tasksQuery = realm.where(ProjectTask::class.java) Log.i("EXAMPLE", "Ali has completed " + tasksQuery.equalTo("assignee", "Ali").and() .equalTo("isComplete", true).findAll().size + " tasks.")
string演算子
これらの string 演算子を使用して、string の値を比較できます。 正規表現のようなワイルドカードを使用すると、検索の柔軟性が向上します。
演算子 | 説明 |
---|---|
beginsWith | 左側の文字string式が右側のstring式で始まる場合は、 true と評価されます。 これは contains と似ていますが、左側のstring式が右側のstring式の先頭にある場合にのみ一致します。 |
contains | 左側のstring式が右側のstring式のどこにある場合は、 true と評価されます。 |
endsWith | 左側の文字string式が右側のstring式で終わる場合は、 true と評価されます。 これは contains と似ていますが、左側のstring式が右側のstring式の最後に見つかった場合にのみ一致します。 |
like | 左側の string 式が右側の string ワイルドカード string 式と一致する場合、
たとえば、ワイルドカードstring 「d?g」は、「dog」、「dig」、および「dgs」と一致しますが、「ding」、「dg」、または「adog」には一致しません。 |
equalTo | 左側の文字列が右側のstringと辞書的に等しい場合、 true と評価されstring 。 |
例
クエリ エンジンの string 演算子を使用して、名前が文字「e」で始まるプロジェクトと、名前に「ie」が含まれるプロジェクトを検索します。
RealmQuery<Project> projectsQuery = realm.where(Project.class); // Pass Case.INSENSITIVE as the third argument for case insensitivity. Log.i("EXAMPLE", "Projects that start with 'e': " + projectsQuery.beginsWith("name", "e", Case.INSENSITIVE).count()); Log.i("EXAMPLE", "Projects that contain 'ie': " + projectsQuery.contains("name", "ie").count());
val projectsQuery = realm.where(Project::class.java) // Pass Case.INSENSITIVE as the third argument for case insensitivity. Log.i("EXAMPLE", "Projects that start with 'e': " + projectsQuery.beginsWith("name", "e", Case.INSENSITIVE).count()) Log.i("EXAMPLE", "Projects that contain 'ie': " + projectsQuery.contains("name", "ie").count())
注意
大文字と小文字を区別しない文字の制限
大文字と小文字を区別しないstring演算子は、Latin Basic
、Latin Supplement
、Latin Extended A
、Latin Extended B (UTF-8 range 0–591)
文字セットのみをサポートします。 equalTo
、 notEqualTo
、 contains
、 endsWith
、 beginsWith
、またはlike
を使用する場合に、クエリで大文字と小文字を区別しないフラグを設定すると、英語のロケール文字でのみ機能します。
集計演算子
Realm オブジェクトのコレクション プロパティに集計演算子を適用できます。 集計演算子はコレクションを走査して、単一の値に縮小します。
演算子 | 説明 |
---|---|
average | コレクション全体の特定の数値プロパティの平均値を評価します。 |
count | 指定されたコレクション内のオブジェクトの数を評価します。 |
max | コレクション全体で特定の数値プロパティの最も高い値を評価します。 |
min | コレクション全体で特定の数値プロパティの最小値として評価されます。 |
sum | コレクション全体の指定された数値プロパティの合計を評価します。 |
例
データのさまざまなファセットを表示するために、フィルターがいくつか作成されます。
タスクの平均優先順位が 5 を超えるプロジェクト。
長時間実行されているプロジェクト。
RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class); /* Aggregate operators do not support dot-notation, so you cannot directly operate on a property of all of the objects in a collection property. You can operate on a numeric property of the top-level object, however: */ Log.i("EXAMPLE", "Tasks average priority: " + tasksQuery.average("priority"));
val tasksQuery = realm.where(ProjectTask::class.java) /* Aggregate operators do not support dot-notation, so you cannot directly operate on a property of all of the objects in a collection property. You can operate on a numeric property of the top-level object, however: */Log.i("EXAMPLE", "Tasks average priority: " + tasksQuery.average("priority"))
フィルタリング、ソート、制限、一意、チェーンのクエリ
このセクションの例について
このセクションの例では、 Teacher
とStudent
という 2 つの Realm オブジェクトタイプを使用します。
これら 2 つのクラスのスキーマは以下を参照してください。
import io.realm.RealmList; import io.realm.RealmObject; public class Teacher extends RealmObject { private String name; private Integer numYearsTeaching; private String subject; private RealmList<Student> students; public Teacher() {} public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getNumYearsTeaching() { return numYearsTeaching; } public void setNumYearsTeaching(Integer numYearsTeaching) { this.numYearsTeaching = numYearsTeaching; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public RealmList<Student> getStudents() { return students; } public void setStudents(RealmList<Student> students) { this.students = students; } }
import io.realm.RealmObject; import io.realm.RealmResults; import io.realm.annotations.LinkingObjects; public class Student extends RealmObject { private String name; private Integer year; private final RealmResults<Teacher> teacher = null; public Student() {} public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getYear() { return year; } public void setYear(Integer year) { this.year = year; } public RealmResults<Teacher> getTeacher() { return teacher; } }
import io.realm.RealmList import io.realm.RealmObject open class Teacher : RealmObject() { var name: String? = null var numYearsTeaching: Int? = null var subject: String? = null var students: RealmList<Student>? = null }
import io.realm.RealmObject import io.realm.RealmResults import io.realm.annotations.LinkingObjects open class Student : RealmObject() { var name: String? = null var year: Int? = null val teacher: RealmResults<Teacher>? = null }
フィルター
スムーズインターフェース の演算子メソッドを使用してフィルターを構築できます RealmQuery クラスによって公開される場合
// Build the query looking at all teachers: RealmQuery<Teacher> query = realm.where(Teacher.class); // Add query conditions: query.equalTo("name", "Ms. Langtree"); query.or().equalTo("name", "Mrs. Jacobs"); // Execute the query: RealmResults<Teacher> result1 = query.findAll(); // Or alternatively do the same all at once (the "Fluent interface"): RealmResults<Teacher> result2 = realm.where(Teacher.class) .equalTo("name", "Ms. Langtree") .or() .equalTo("name", "Mrs. Jacobs") .findAll();
// Build the query looking at all teachers: val query = realm.where(Teacher::class.java) // Add query conditions: query.equalTo("name", "Ms. Langtree") query.or().equalTo("name", "Mrs. Jacobs") // Execute the query: val result1 = query.findAll() // Or alternatively do the same all at once (the "Fluent interface"): val result2 = realm.where(Teacher::class.java) .equalTo("name", "Ms. Langtree") .or() .equalTo("name", "Mrs. Jacobs") .findAll()
これにより、「Ms」という名前の指示を含む、クラスRealmResultsの新しいインスタンスが作成されます。 Longtree" または "数: James .
RealmQuery
には、クエリを実行できるいくつかのメソッドが含まれています。
findAll()は、クエリ条件を満たすすべてのオブジェクトを検索するまでブロックします
findAllAsync()はすぐに戻り、クエリ条件を満たすすべてのオブジェクトをバックグラウンド スレッドで非同期に検索します
findFirst()は、クエリ条件を満たす最初のオブジェクトを見つけるまでブロックします
findFirstAsync()はすぐに戻り、バックグラウンド スレッドで非同期にクエリ条件を満たす最初のオブジェクトを検索します。
クエリは、 RealmResults型を使用して、一致する Realm オブジェクトへの参照のリストを返します。
リンク クエリ
オブジェクト プロパティを参照する場合、ドット表記を使用してそのオブジェクトの子プロパティを参照できます。 ドット表記 で埋め込みオブジェクトと関係のプロパティを参照できます。
たとえば、"Wirt" または "Greg" という名前の学生が所属するすべてのドライバーに対するクエリを考えてみましょう。
// Find all teachers who have students with the names "Wirt" or "Greg" RealmResults<Teacher> result = realm.where(Teacher.class) .equalTo("students.name", "Wirt") .or() .equalTo("students.name", "Greg") .findAll();
// Find all teachers who have students with the names "Wirt" or "Greg" val result = realm.where(Teacher::class.java) .equalTo("students.name", "Wirt") .or() .equalTo("students.name", "Greg") .findAll()
ドット表記を使用して逆関係をクエリすることもできます。
// Find all students who have teachers with the names "Ms. Langtree" or "Mrs. Jacobs" RealmResults<Student> result = realm.where(Student.class) .equalTo("teacher.name", "Ms. Langtree") .or() .equalTo("teacher.name", "Mrs. Jacobs") .findAll();
// Find all students who have teachers with the names "Ms. Langtree" or "Mrs. Jacobs" val result = realm.where(Student::class.java) .equalTo("teacher.name", "Ms. Langtree") .or() .equalTo("teacher.name", "Mrs. Jacobs") .findAll()
結果を並べ替える
重要
Realm は、 distinct()
、 sort()
、 limit()
メソッドを指定した順序で適用します。 データセットによっては、クエリ結果が変更される可能性があります。 一般的に、意図しない結果セットを避けるためには、最後にlimit()
を適用する必要があります。
sort()メソッドを使用してクエリ結果の順序を定義できます。
// Find all students in year 7, and sort them by name RealmResults<Student> result = realm.where(Student.class) .equalTo("year", 7) .sort("name") .findAll(); // Alternatively, find all students in year 7 RealmResults<Student> unsortedResult = realm.where(Student.class) .equalTo("year", 7) .findAll(); // then sort the results set by name RealmResults<Student> sortedResult = unsortedResult.sort("name");
// Find all students in year 7, and sort them by name val result: RealmResults<Student> = realm.where(Student::class.java) .equalTo("year", 7L) .sort("name") .findAll() // Alternatively, find all students in year 7 val unsortedResult: RealmResults<Student> = realm.where(Student::class.java) .equalTo("year", 7L) .findAll() // then sort the results set by name val sortedResult = unsortedResult.sort("name")
ソートは、デフォルトで結果を昇順で整理します。 結果を降順で並べ替えるには、2 番目の引数としてSort.DESCENDING
を渡します。 単一のプロパティではなくプロパティの配列を渡すことで、同一のプロパティ値間のソート順序の同値を解決できます。同点の場合、Realm は関連付けられているオブジェクトを後続のプロパティで順番にソートします。
注意
stringソートの制限
Realm は大文字と小文字に対して非標準のソートを使用し、大文字が最初にソートされるのではなく、まとめてソートされます。 その結果、 '- !"#0&()*,./:;?_+<=>123aAbBcC...xXyYzZ
が Realm の実際のソート順になります。 また、文字列のソートでは、 Latin Basic
、 Latin Supplement
、 Latin Extended A
、 Latin Extended B (UTF-8 range 0–591)
文字セットのみがサポートされます。
結果を制限する
limit()メソッドを使用して、クエリ結果の数を特定の最大数に制限できます。
// Find all students in year 8, and limit the results collection to 10 items RealmResults<Student> result = realm.where(Student.class) .equalTo("year", 8) .limit(10) .findAll();
// Find all students in year 8, and limit the results collection to 10 items val result: RealmResults<Student> = realm.where(Student::class.java) .equalTo("year", 8L) .limit(10) .findAll()
限定的な結果コレクションは、他のクエリ結果と同様に自動的に更新されます。 その結果、基礎となるデータの変更として、オブジェクトがコレクションから削除される可能性があります。
Tip
Realm の最適化ではページ分割は必要ありません
一部のデータベースでは、ディスクから不要なデータを読み取ったり、メモリを使用しすぎたりするのを避けるために、結果を制限してページ分割することを推奨しています。
Realm クエリは遅延されるため、このような測定を行う必要はありません。 Realm は、明示的にアクセスされた場合にのみ、クエリ結果からオブジェクトをロードします。
Tip
限定的な結果での削除通知
コレクション通知では、結果セットから削除されたオブジェクトが削除されたと報告されます。 これは必ずしも基礎の Realm から削除されたことを意味するわけではなく、クエリ結果の一部ではなくなったことを意味します。
一意の結果
distinct()メソッドを使用して、特定のフィールドのクエリ結果を一意の値に縮小できます。
// Find all students in year 9, and cap the result collection at 10 items RealmResults<Student> result = realm.where(Student.class) .equalTo("year", 9) .distinct("name") .findAll();
// Find all students in year 9, and cap the result collection at 10 items val result: RealmResults<Student> = realm.where<Student>(Student::class.java) .equalTo("year", 9L) .distinct("name") .findAll()
distinct()
は、整数、long、短い、およびString
フィールドでのみ呼び出せます。他のフィールド型では例外がスローされます。 ソートと同様に、同点を解決するために複数のフィールドを指定できます。
チェーン クエリ
where()メソッドを呼び出すと、結果コレクションに追加のフィルターを適用できます。
// Find all students in year 9 and resolve the query into a results collection RealmResults<Student> result = realm.where(Student.class) .equalTo("year", 9) .findAll(); // filter the students results again by teacher name RealmResults<Student> filteredResults = result.where().equalTo("teacher.name", "Ms. Langtree").findAll();
// Find all students in year 9 and resolve the query into a results collection val result: RealmResults<Student> = realm.where(Student::class.java) .equalTo("year", 9L) .findAll() // filter the students results again by teacher name val filteredResults = result.where().equalTo("teacher.name", "Ms. Langtree").findAll()
where()
メソッドから返されるRealmQuery
は、 find
メソッドを使用してRealmResults
に解決できます。 フィルタリングされた結果では、元の結果セットと同じタイプのオブジェクトのみが返されますが、それ以外の場合は任意のフィルターを使用できます。
RQLを使用したクエリ
バージョン 10.4.0 の新機能。
また、Realm からオブジェクトを取得するときに検索を制限する string ベースのクエリ言語であるRQLを使用してRealmをクエリすることもできます。
RealmQuery.rawPredate()を使用できます。 構文、使用、および制限の詳細については、 RQLリファレンスを参照してください。
RQLでは、 Realmモデル クラスで定義されたクラス名とプロパティ名、または @RealmField
で定義された内部名のいずれかを使用できます。 未加工の述語を、 RealmQuery
で作成された他の未加工の述語またはタイプセーフな述語と組み合わせることができます。
// Build a RealmQuery based on the Student type RealmQuery<Student> query = realm.where(Student.class); // Simple query RealmResults<Student> studentsNamedJane = query.rawPredicate("name = 'Jane'").findAll(); // Multiple predicates RealmResults<Student> studentsNamedJaneOrJohn = query.rawPredicate("name = 'Jane' OR name = 'John'").findAll(); // Collection queries RealmResults<Student> studentsWithTeachers = query.rawPredicate("teacher.@count > 0").findAll(); RealmResults<Student> studentsWithSeniorTeachers = query.rawPredicate("ALL teacher.numYearsTeaching > 5").findAll(); // Sub queries RealmResults<Student> studentsWithMathTeachersNamedSteven = query.rawPredicate("SUBQUERY(teacher, $teacher, $teacher.subject = 'Mathematics' AND $teacher.name = 'Mr. Stevens').@count > 0").findAll(); // Sort, Distinct, Limit RealmResults<Student> students = query.rawPredicate("teacher.@count > 0 SORT(year ASCENDING) DISTINCT(name) LIMIT(5)").findAll(); // Combine two raw predicates RealmResults<Student> studentsNamedJaneOrHenry = query.rawPredicate("name = 'Jane'") .rawPredicate("name = 'Henry'").findAll(); // Combine raw predicate with type-safe predicate RealmResults<Student> studentsNamedJaneOrHenryAgain = query.rawPredicate("name = 'Jane'") .equalTo("name", "Henry").findAll();
// Build a RealmQuery based on the Student type val query = realm.where(Student::class.java) // Simple query val studentsNamedJane = query.rawPredicate("name = 'Jane'").findAll() // Multiple predicates val studentsNamedJaneOrJohn = query.rawPredicate("name = 'Jane' OR name = 'John'").findAll() // Collection queries val studentsWithTeachers = query.rawPredicate("teacher.@count > 0").findAll() val studentsWithSeniorTeachers = query.rawPredicate("ALL teacher.numYearsTeaching > 5").findAll() // Sub queries val studentsWithMathTeachersNamedSteven = query.rawPredicate("SUBQUERY(teacher, \$teacher, \$teacher.subject = 'Mathematics' AND \$teacher.name = 'Mr. Stevens').@count > 0") .findAll() // Sort, Distinct, Limit val students = query.rawPredicate("teacher.@count > 0 SORT(year ASCENDING) DISTINCT(name) LIMIT(5)") .findAll() // Combine two raw predicates val studentsNamedJaneOrHenry = query.rawPredicate("name = 'Jane'") .rawPredicate("name = 'Henry'").findAll() // Combine raw predicate with type-safe predicate val studentsNamedJaneOrHenryAgain = query.rawPredicate("name = 'Jane'") .equalTo("name", "Henry").findAll()