Filtrar dados - SDK Java
Nesta página
- Mecanismo de query
- Interface fluente
- Sobre os exemplos nesta seção
- Operadores de comparação
- Operadores lógicos
- Operadores de strings
- Operadores agregados
- Filtrar, Classificar, Limitar, Único e Consultas de queries
- Sobre os exemplos nesta seção
- Filtros
- Classificar resultados
- Limitar resultados
- Resultados únicos
- Consultas em cadeia
- Consulta com linguagem de query de realm
Mecanismo de query
Para filtrar dados em seu domínio, use o mecanismo de query Realm.
Existem duas maneiras de acessar o mecanismo de consulta com o Java SDK:
Interface fluente
O Java SDK usa uma interface fluente para construir queries de múltiplas cláusulas que são passadas para o mecanismo de query.
Consulte API do RealmQuery para obter uma lista completa dos métodos disponíveis.
Há vários tipos de operadores disponíveis para filtrar uma Collection do Realm. Os filtros funcionam avaliando uma expressão de operador para cada objeto na collection que está sendo filtrada. Se a expressão resolver para true
, o banco de dados do Realm incluirá o objeto na collection de resultados.
Uma expressão consiste em um dos seguintes:
O nome de uma propriedade do objeto que está sendo avaliados.
Um operador e até duas expressões de argumentos.
Uma string literal, número ou data.
Sobre os exemplos nesta seção
Os exemplos nesta seção usam um conjunto de dados simples para uma aplicação de lista de tarefas. Os dois tipos de objetos do Realm são Project
e Task
. Task
tem um nome, o nome do responsável e um sinalizador finalizado. Há também um número arbitrário de prioridade (o maior é mais importante) e o número de minutos gastos trabalhando nisso. Um Project
tem zero ou mais Tasks
.
Consulte o esquema para estas duas classes, Project
e Task
, abaixo:
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 comparação
A operação mais direta em uma pesquisa é a comparação de valores.
Operador | Descrição |
---|---|
between | Avalia como true se a expressão numérica ou de data à esquerda estiver entre ou igual ao intervalo à direita. Para datas, isso é avaliado como true se a data à esquerda estiver dentro do intervalo de datas à direita. |
equalTo | Avalia para true se a expressão do lado esquerdo é igual à expressão do lado direito. |
greaterThan | Avalia como true se a expressão numérica ou de data do lado esquerdo é maior que a expressão numérica ou de data do lado direito. Com datas, avalia como true se a data do lado esquerdo é posterior à data do lado direito. |
greaterThanOrEqualTo | Avalia como true se a expressão numérica ou de data do lado esquerdo é maior ou igual à expressão numérica ou de data do lado direito. Com datas, avalia como true se a data do lado esquerdo é posterior ou igual à data do lado direito. |
in | Avalia como true se a expressão da esquerda estiver na lista da direita. |
lessThan | Avalia como true se a expressão numérica ou de data do lado esquerdo é menor que a expressão numérica ou de data do lado direito. Com datas, avalia como true se a data do lado esquerdo é anterior à data do lado direito. |
lessThanOrEqualTo | Avalia como true se a expressão numérica à esquerda for menor ou igual à expressão numérica à direita. Com datas, avalia como true se a data do lado esquerdo é anterior ou igual à data do lado direito. |
notEqualTo | Avalia como true se a expressão do lado esquerdo não é igual à expressão do lado direito. |
Exemplo
O exemplo a seguir usa operadores de comparação do mecanismo de consulta para:
Encontre tarefas de alta prioridade comparando o valor da propriedade
priority
com um número limite, acima do qual a prioridade pode ser considerada alta.Encontre tarefas recém-iniciadas ou de curta duração verificando se a propriedade
progressMinutes
está dentro de um determinado intervalo.Encontre tarefas não atribuídas encontrando tarefas onde a propriedade
assignee
é igual anull
.Encontre tarefas atribuídas a membros específicos da equipe Ali ou Jamie verificando se a propriedade
assignee
está em uma lista de nomes.
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
Você pode fazer predicados compostos usando operadores lógicos.
Operador | Descrição |
---|---|
and | Avalia para true se as expressões da esquerda e da direita forem true . |
not | Nega o resultado da expressão fornecida. |
or | Avalia como true se qualquer uma das expressões retornar true . |
Exemplo
Podemos usar os operadores lógicos da linguagem de consulta para encontrar todas as tarefas concluídas de Ali. Ou seja, encontramos todas as tarefas em que o valor da propriedade assignee
é igual a "Ali" E o valor da propriedade 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.")
Operadores de strings
Você pode comparar valores de string utilizando esses operadores de string. Curingas do tipo Regex permitem mais flexibilidade na pesquisa.
Operador | Descrição |
---|---|
beginsWith | Avalia como true se a expressão de string à esquerda começar com a expressão de string à direita. Isso é semelhante ao contains , mas só corresponde se a expressão de string à esquerda for encontrada no início da expressão de string à direita. |
contains | Avaliado como true se a expressão de string à esquerda for encontrada em qualquer lugar na expressão de string à direita. |
endsWith | Avalia como true se a expressão de string à esquerda terminar com a expressão de string à direita. Isso é semelhante ao contains , mas só corresponde se a expressão de cadeia de caracteres à esquerda for encontrada no final da expressão de cadeia de caracteres à direita. |
like | Avalia como
Por exemplo, a cadeia curinga "d?g" corresponde a "dog", "dig" e "cavg", mas não "ding", "dg" ou "a dog". |
equalTo | Avalia como true se a string esquerda for lexicograficamente igual à string direita. |
Exemplo
Usamos os operadores de cadeia de caracteres do mecanismo de consulta para encontrar projetos com um nome que comece com a letra "e" e projetos com nomes que contenham "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())
Observação
Limitações de caracteres que não diferenciam maiúsculas de minúsculas
Os operadores de string que não diferenciam maiúsculas de minúsculas suportam somente os conjuntos de caracteres Latin Basic
, Latin Supplement
, Latin Extended A
e Latin Extended B (UTF-8 range 0–591)
. A definição do sinalizador de distinção entre maiúsculas e minúsculas em queries ao usar equalTo
, notEqualTo
, contains
, endsWith
, beginsWith
ou like
só funciona com caracteres de localidade em inglês.
Operadores agregados
Você pode aplicar um operador agregado a uma propriedade de collection de um objeto Realm. Operadores agregados atravessam uma collection e a reduzem para um único valor.
Operador | Descrição |
---|---|
average | Avalia conforme o valor médio de uma determinada propriedade numérica em uma coleção. |
count | Avalia o número de objetos na coleção fornecida. |
max | Avalia conforme o valor mais alto de uma determinada propriedade numérica em uma collection. |
min | Avalia conforme o valor mais baixo de uma determinada propriedade numérica em uma collection. |
sum | Avalia conforme a soma de uma determinada propriedade numérica em uma collection. |
Exemplo
Criamos alguns filtros para mostrar facetas diferentes dos dados:
Projetos com prioridade média de tarefas acima de 5.
Projetos de longa duração.
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"))
Filtrar, Classificar, Limitar, Único e Consultas de queries
Sobre os exemplos nesta seção
Os exemplos nesta seção usam dois tipos de objeto de Realm: Teacher
e Student
.
Consulte o esquema para estas duas classes abaixo:
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
Você pode criar filtros usando os métodos do operador da interface fluente exposta pela classe 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()
Isso lhe dá uma nova instância da classe RealmResults, contendo professores com o nome "Sra. Langtree" ou "Sra. Jacobs".
RealmQuery
inclui vários métodos que podem executar queries:
findAll() bloqueia até encontrar todos os objetos que atendem às condições da query
findAllAsync() é retornado imediatamente e encontra todos os objetos que atendem às condições da query de maneira assíncrona em uma thread de background
Blocos findFirst() até encontrar o primeiro objeto que atenda às condições de query
findFirstAsync() retorna imediatamente e encontra o primeiro objeto que atende às condições da query de forma assíncrona em um thread em segundo plano
As queries retornam uma lista de referências aos objetos do Realm correspondentes usando o tipo RealmResults.
Vincular queries
Quando fizer referência a uma propriedade de objeto, você pode usar a notação de ponto para se referir a propriedades derivadas desse objeto. Você pode fazer referência às propriedades de objetos embarcados e relacionamentos com notação de ponto.
Por exemplo, considere uma query para todos os professores com um aluno chamado "Wirt" ou "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()
Você pode até usar notação de ponto para consultar relacionamentos inversos:
// 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()
Classificar resultados
Importante
O Realm aplica os métodos distinct()
, sort()
e limit()
na ordem que você especifica. Dependendo do conjunto de dados, isto pode alterar o resultado da query. Geralmente, você deve aplicar limit()
por último para evitar conjuntos de resultados indesejados.
Você pode definir a ordem dos resultados da query usando o 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")
As classificações organizam os resultados em ordem crescente por padrão. Para organizar os resultados em ordem decrescente, passe Sort.DESCENDING
como segundo argumento. Você pode resolver empates de ordem de classificação entre valores de propriedade idênticos passando uma array de propriedades em vez de uma única propriedade: no caso de um empate, Realm classifica os objetos empatados por propriedades subsequentes em ordem.
Observação
Limitações de classificação de strings
O Realm usa uma classificação não padrão para letras maiúsculas e minúsculas, classificando-as juntas em vez de primeiro classificá-las em maiúsculas. Como resultado, '- !"#0&()*,./:;?_+<=>123aAbBcC...xXyYzZ
é a ordem de classificação real no Realm. Além disso, a classificação de strings só é compatível com os conjuntos de caracteres Latin Basic
, Latin Supplement
, Latin Extended A
e Latin Extended B (UTF-8 range 0–591)
.
Limitar resultados
Você pode limitar o número de resultados da query a um número máximo específico usando o 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()
Collections de resultados limitadas são atualizadas automaticamente como qualquer outro resultado de query. Consequentemente, os objetos podem sair da collection à medida que os dados subjacentes são alterados.
Dica
A paginação não é necessária para Otimização de Realm
Alguns bancos de dados incentivam a paginação de resultados com limites para evitar a leitura de dados desnecessários do disco ou o uso excessivo de memória.
Como as queries do Realm são lentas, não há necessidade de tomar essas medidas. O Realm somente carrega objetos dos resultados da query quando eles são explicitamente acessados.
Dica
Notificações excluídas em resultados limitados
As notificações de collection relatam objetos como excluídos quando saem do conjunto de resultados. Isso não significa necessariamente que eles foram excluídos do domínio subjacente, apenas que não fazem mais parte do resultado da query.
Resultados únicos
Você pode reduzir os resultados da query para valores únicos para um determinado campo ou campos usando o 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()
Você só pode chamar distinct()
em campos inteiros, longos, curtos e String
; outros tipos de campo lançarão uma exceção. Assim como na classificação, você pode especificar vários campos para resolver empates.
Consultas em cadeia
Você pode aplicar filtros adicionais a uma coleção de resultados chamando o método onde():
// 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()
O método where()
retorna um RealmQuery
que você pode resolver em um RealmResults
utilizando um método find
. Os resultados filtrados só podem retornar objetos do mesmo tipo que o conjunto de resultados originais, mas de outra forma podem usar quaisquer filtros.
Consulta com linguagem de query de realm
Novidades na versão 10.4.0.
Você também pode realizar query no Realm usando o Realm Query Language, uma string baseada em linguagem de query para limitar as pesquisa ao recuperar objetos de um realm.
Você pode usar RealmQuery.rawPredicate(). Para obter mais informações sobre sintaxe, uso e limitações, consulte a referência da RQL.
O Realm Query Language pode usar os nomes de classe e de propriedade definidos nas classes do modelo Realm ou os nomes internos definidos com @RealmField
. Você pode combinar predicados brutos com outros predicados brutos ou predicados seguros por tipo criados com 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()
Dica
Veja também: Exemplos da linguagem de query do Realm
Você também pode encontrar exemplos úteis de linguagem de query do Realm nas seguintes páginas: