Query Engine
Para filtrar datos en tu entorno, utiliza el motor de query de Realm.
There are two ways to access the query engine with the Java SDK:
Fluent Interface
El SDK de Java utiliza una interfaz Fluent para construir consultas de múltiples cláusulas que se pasan al motor de consultas.
See RealmQuery API for a complete list of available methods.
Hay varios tipos de operadores disponibles para filtrar una colección de Realm. Los filtros funcionan evaluando una expresión de operador para cada objeto de la colección que se filtra. Si la expresión se resuelve como trueLa base de datos Realm incluye el objeto en la colección de resultados.
An expression consists of one of the following:
The name of a property of the object currently being evaluated.
An operator and up to two argument expression(s).
A literal string, number, or date.
About the Examples In This Section
The examples in this section use a simple data set for a task list app. The two Realm object types are Project and Task. A Task has a name, assignee's name, and completed flag. There is also an arbitrary number for priority (higher is more important) and a count of minutes spent working on it. A Project has zero or more Tasks.
See the schema for these two classes, Project and Task, below:
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()
Operadores de comparación
The most straightforward operation in a search is to compare values.
Operador | Descripción |
|---|---|
| Evaluates to |
equalTo | Evaluates to |
greaterThan | Evaluates to |
greaterThanOrEqualTo | Evaluates to |
| Evaluates to |
lessThan | Devuelve |
lessThanOrEqualTo | Se evalúa como |
notEqualTo | Evaluates to |
Ejemplo
The following example uses the query engine's comparison operators to:
Encuentre tareas de alta prioridad comparando el valor de la propiedad
prioritycon un número umbral, por encima del cual la prioridad puede considerarse alta.Find just-started or short-running tasks by seeing if the
progressMinutesproperty falls within a certain range.Find unassigned tasks by finding tasks where the
assigneeproperty is equal tonull.Find tasks assigned to specific teammates Ali or Jamie by seeing if the
assigneeproperty is in a list of names.
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())
Operadores lógicos
You can make compound predicates using logical operators.
Operador | Descripción |
|---|---|
and | Se evalúa como |
not | Negates the result of the given expression. |
or | Evaluates to |
Ejemplo
We can use the query language's logical operators to find all of Ali's completed tasks. That is, we find all tasks where the assignee property value is equal to 'Ali' AND the isComplete property value is 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.")
Operadores de String
You can compare string values using these string operators. Regex-like wildcards allow more flexibility in search.
Operador | Descripción |
|---|---|
beginsWith | Se evalúa como |
| Evalúa como |
endsWith | Evaluates to |
like | Evaluates to
For example, the wildcard string "d?g" matches "dog", "dig", and "dug", but not "ding", "dg", or "a dog". |
equalTo | Evaluates to |
Ejemplo
We use the query engine's string operators to find projects with a name starting with the letter 'e' and projects with names that contain '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())
Nota
Limitaciones de caracteres que no distinguen entre mayúsculas y minúsculas
Los operadores de strings que no distinguen entre mayúsculas y minúsculas solo soportan los conjuntos de caracteres Latin Basic, Latin Supplement, Latin Extended A y Latin Extended B (UTF-8 range 0–591). Establecer la indicación de insensibilidad a mayúsculas y minúsculas en las queries al usar equalTo, notEqualTo, contains, endsWith, beginsWith o like solo funciona con caracteres de la localización inglesa.
Aggregate Operators
Se puede aplicar un operador de agregación a una propiedad de colección de un objeto Realm. Los operadores de agregación recorren una colección y la reducen a un único valor.
Operador | Descripción |
|---|---|
average | Se evalúa como el valor promedio de una propiedad numérica dada en una colección. |
count | Evalúa al número de objetos en la colección dada. |
max | Evaluates to the highest value of a given numerical property across a collection. |
min | Evaluates to the lowest value of a given numerical property across a collection. |
sum | Evaluates to the sum of a given numerical property across a collection. |
Ejemplo
We create a couple of filters to show different facets of the data:
Projects with average tasks priority above 5.
Long running projects.
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"))
Filter, Sort, Limit, Unique, and Chain Queries
About the Examples in This Section
The examples in this section use two Realm object types: Teacher and Student.
See the schema for these two classes below:
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 }
Filtros
Puedes compilar filtros utilizando los métodos operadores de la interfaz fluida que expone la clase 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()
Esto le proporciona una nueva instancia de la clase RealmResults, que contiene profesores con el nombre "Sra. Langtree" o "Sra. Jacobs".
RealmQuery includes several methods that can execute queries:
findAll() se bloquea hasta que encuentra todos los objetos que cumplen las condiciones de consulta
findAllAsync() regresa inmediatamente y encuentra todos los objetos que cumplen las condiciones de consulta de forma asincrónica en un hilo en segundo plano.
findFirst() blocks until it finds the first object that meets the query conditions
findFirstAsync() returns immediately and finds the first object that meets the query conditions asynchronously on a background thread
Queries return a list of references to the matching Realm objects using the RealmResults type.
Consultas de enlace
When referring to an object property, you can use dot notation to refer to child properties of that object. You can refer to the properties of embedded objects and relationships with dot notation.
For example, consider a query for all teachers with a student named "Wirt" or "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()
You can even use dot notation to query inverse relationships:
// 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()
Ordenar resultados
Importante
Realm applies the distinct(), sort() and limit() methods in the order you specify. Depending on the data set this can alter the query result. Generally, you should apply limit() last to avoid unintended result sets.
Puede definir el orden de los resultados de la consulta utilizando el método 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")
Sorts organize results in ascending order by default. To organize results in descending order, pass Sort.DESCENDING as a second argument. You can resolve sort order ties between identical property values by passing an array of properties instead of a single property: in the event of a tie, Realm sorts the tied objects by subsequent properties in order.
Nota
String Sorting Limitations
Realm uses non-standard sorting for upper and lowercase letters, sorting them together rather than sorting uppercase first. As a result, '- !"#0&()*,./:;?_+<=>123aAbBcC...xXyYzZ is the actual sorting order in Realm. Additionally, sorting strings only supports the Latin Basic, Latin Supplement, Latin Extended A, and Latin Extended B (UTF-8 range 0–591) character sets.
Limitar los resultados
Puede limitar el número de resultados de la consulta a un número máximo específico utilizando el método 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()
Las colecciones de resultados limitadas se actualizan automáticamente como cualquier otro resultado de consulta. Por lo tanto, los objetos podrían desaparecer de la colección a medida que cambian los datos subyacentes.
Tip
La paginación no es necesaria para la optimización del dominio
Algunas bases de datos incentivan la paginación de los resultados con límites para evitar leer datos innecesarios del disco o usar demasiada memoria.
Dado que las queries de Realm son perezosas, no es necesario tomar tales medidas. Realm solo carga objetos de los resultados de queries cuando se accede a ellos explícitamente.
Tip
Deleted Notifications in Limited Results
notificaciones de la colección reportan objetos como eliminados cuando desaparecen del conjunto de resultados. Esto no significa necesariamente que se hayan eliminado del realm subyacente, solo que ya no forman parte del resultado de la query.
Unique Results
Puede reducir los resultados de la consulta a valores únicos para un campo o campos determinados utilizando el método 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()
Sólo puedes llamar a distinct() en campos de tipo entero, largo, corto y String; otros tipos de campo lanzarán una excepción. Al igual que con la ordenación, puedes especificar varios campos para resolver empates.
Chain Queries
Puede aplicar filtros adicionales a una colección de resultados llamando al método 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()
El where() método devuelve un RealmQuery que se puede convertir en un RealmResults mediante un find método. Los resultados filtrados solo pueden devolver objetos del mismo tipo que el conjunto de resultados original, pero pueden usar cualquier otro filtro.
Query with Realm Query Language
New in version 10.4.0.
También puedes consultar realms usando Realm Query Language, un languaje del query basado en texto string para restringir búsqueda al obtener objeto de un realm.
Puedes utilizar RealmQuery.rawPredicate(). Para más información sobre sintaxis, uso y limitaciones, consulta la referencia del Lenguaje de Consulta de Realm.
Realm Query Language can use either the class and property names defined in your Realm Model classes or the internal names defined with @RealmField. You can combine raw predicates with other raw predicates or type-safe predicates created with 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()
Tip
Realm Query Language Examples
You can also find useful Realm Query Language examples on the following pages: