Puede volver a leer los datos que ha almacenado en la base de datos buscando, filtrando y ordenando objetos.
Una lectura de la base de datos generalmente consta de los siguientes pasos:
Obtener todos los objetos de un determinado tipo de la base de datos.
Opcionalmente, puedes filtrar los resultados.
Las operaciones de consulta devuelven un recopilación de resultadosEstas colecciones están activas, lo que significa que siempre contienen los últimos resultados de la consulta asociada.
Leer Características
Diseñe los patrones de acceso a datos de su aplicación en torno a estas tres características de lectura clave para leer los datos de la manera más eficiente posible.
Los resultados no son copias
Los resultados de una consulta no son copias de sus datos. Modificar los resultados de una consulta modifica directamente los datos en el disco. Esta asignación de memoria también significa que los resultados están en tiempo real: es decir, siempre reflejan el estado actual del disco.
Los resultados son perezosos
El SDK solo ejecuta una consulta cuando se solicitan los resultados. Esta evaluación diferida permite escribir código de alto rendimiento para gestionar grandes conjuntos de datos y consultas complejas. Se pueden encadenar varias operaciones de filtrado sin necesidad de procesar el estado intermedio.
Se conservan las referencias
Una ventaja del modelo de objetos del SDK es que este conserva automáticamente todas las relaciones de un objeto como referencias directas. Esto permite recorrer el gráfico de relaciones directamente a través de los resultados de una consulta.
Una referencia directa, o puntero, te permite acceder directamente a las propiedades de un objeto relacionado a través de la referencia.
Otras bases de datos suelen copiar objetos del almacenamiento de la base de datos a la memoria de la aplicación cuando necesitas trabajar directamente con ellos. Debido a que los objetos de la aplicación contienen referencias directas, tienes la siguiente opción: copiar el objeto al que se hace referencia en cada referencia directa fuera de la base de datos en caso de que sea necesario, o simplemente copiar la clave externa de cada objeto y hacer query para el objeto con esa clave si se accede a él. Si eliges copiar objetos referenciados a la memoria de la aplicación, puedes usar muchos recursos para objetos a los que nunca se accede, pero si elige solo copiar la clave externa, las búsquedas de objetos referenciados pueden causar que su aplicación se vuelva lenta.
El SDK evita todo esto mediante objetos activos de copia cero. Los accesores de objetos del SDK apuntan directamente al almacenamiento de la base de datos mediante mapeo de memoria, por lo que no hay distinción entre los objetos en la base de datos y los resultados de la consulta en la memoria de la aplicación. Gracias a esto, se pueden recorrer referencias directas en toda una base de datos desde cualquier resultado de consulta.
Limitar los resultados de la consulta
Gracias a la evaluación diferida, no se necesita ningún mecanismo especial para limitar los resultados de la consulta con el SDK. Por ejemplo, si la consulta coincide con miles de objetos, pero solo se desea cargar los diez primeros, simplemente se accede únicamente a los diez primeros elementos de la colección de resultados.
Paginación
Gracias a la evaluación diferida, la tarea habitual de paginación se simplifica considerablemente. Por ejemplo, supongamos que tiene una colección de resultados asociada a una consulta que coincide con miles de objetos en su base de datos. Muestra cien objetos por página. Para avanzar a cualquier página, simplemente acceda a los elementos de la colección de resultados comenzando por el índice correspondiente a la página de destino.
Leer objetos
A menos que se indique lo contrario, los ejemplos de esta página utilizan dos tipos de objetos, Person y Team.
() class _Person { () late ObjectId id; late String name; late List<String> hobbies; } () class _Team { () late ObjectId id; late String name; late List<_Person> crew; late RealmValue eventLog; }
Buscar objeto por clave principal
Encuentra un objeto por su clave primaria con Realm.find().
final luke = realm.find<Person>(lukePrimaryKey);
query todos los objetos
Recupera una colección de todos los objetos de un modelo de datos en la base de datos con el Realm.all() método.
final people = realm.all<Person>();
Consultar objetos relacionados
Nuevo en la versión 1.8.0.
Si su modelo de datos incluye objetos que hacen referencia a otros objetos, puede consultar la relación utilizando el método getBacklinks().
Este método devuelve una colección de resultados de todos los objetos vinculados al objeto dado mediante una relación de uno a muchos o inversa. Los siguientes ejemplos utilizan los modelos definidos en la página Relaciones.
Relación de uno a uno: en este ejemplo, tenemos un
Bikemodelo de objeto con una relación de uno a uno con unPersonobjeto.Usamos el método
getBacklinks()para encontrar cualquier objetoBikeque se vincule a la persona especificada a través de la propiedadowner:// 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'); Relación de muchos: en este ejemplo, tenemos un
Scootermodelo de objeto con una relación de muchos con unScooterShopobjeto.Usamos el método
getBacklinks()para encontrar cualquier objetoScooterShopsque se vincule al scooter especificado a través de la propiedad de listascooters:// 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'); Relación inversa: en este ejemplo, tenemos un
Taskmodelo de objeto con una relación inversa con unUserobjeto.Usamos el método
getBacklinks()para encontrar cualquier objetoUserque se vincule a las tareas especificadas a través de la propiedad de vínculos de retrocesotasks:// 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."); } }
Listas de consultas
Puede consultar cualquier lista de RealmObjects o primitivos.
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']);
Consulta de colecciones anidadas de datos mixtos
Nuevo en la versión 2.0.0.
En Flutter SDK v2.0.0 y versiones posteriores, las propiedades RealmValue pueden contener colecciones (una lista o un map) de datos mixtos. Estas colecciones pueden estar anidadas dentro de otras colecciones y pueden contener otras colecciones de datos mixtos.
Puede consultarlos con la misma sintaxis que para una lista o un diccionario normal. Consulte la documentación para obtener más información sobre los operadores compatibles y las comparaciones de listas.
Para colecciones anidadas, también puedes usar:
Notación de corchetes, que proporciona los siguientes operadores del query de colección:
[FIRST]y [LAST]: coincide con el primer o último elemento dentro de la colección.[<int>]: coincide con el elemento en el índice específico.[*]: coincide con cualquier elemento dentro de la colección (este operador asume un tipo de colección en esa ruta).[SIZE]:coincide con la longitud de la colección.
El operador
@type, que admite los siguientes valores:arrayylist: coincide con una colección de listas.dictionaryyobject: coincide con una colección de mapas.collection: coincide con una lista o una colección de mapas.
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` });
Convertir listas o conjuntos en resultados
Puede convertir un RealmList o RealmSet en una instancia de RealmResults utilizando sus respectivos métodos:
Estos métodos admiten listas y conjuntos de RealmObjects así como valores primitivos.
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();
Filtrar resultados
Filtre un RealmList para recuperar un segmento específico de objetos con el método Realm.query(). En el query() argumento del método, utilice el lenguaje de consulta Realm para realizar el filtrado. El lenguaje de consulta Realm es un lenguaje de consulta basado en cadenas que permite recuperar objetos de la base de datos.
final team = realm.query<Team>('name == \$0', ['Millennium Falcon Crew']).first; final humanCrewMembers = team.crew.query('name != \$0', ['Chewbacca']);
Puedes usar argumentos iterables en tu filtro. Por ejemplo:
final listOfNames = ['Luke', 'Leia']; final matchingRealmObjects = realm.query<Person>('name IN \$0', [listOfNames]);
Filtrar relaciones inversas
También puede filtrar por relaciones inversas usando la sintaxis @links.<Type>.<Property>. Por ejemplo, un filtro puede encontrar un objeto Task basándose en las propiedades del objeto User que lo referencia:
// 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'");
Para obtener más información sobre la construcción de consultas, consulte la documentación de referencia del lenguaje de consulta Realm.
Filtrar con búsqueda de texto completo
Puede usar el lenguaje de consulta de dominio (RQL) para consultar propiedades con una anotación de índice de búsqueda de texto completo (FTS). Para consultar estas propiedades, use el TEXT predicado en su consulta.
Excluya los resultados de una palabra colocando el carácter - delante de ella. Por ejemplo, una búsqueda de -sheep wool incluiría todos los resultados de búsqueda de wool, excepto los que contengan sheep.
En la versión y posteriores del SDK de Flutter,1.6.0 se pueden especificar prefijos colocando el * carácter al final de una palabra. Por ejemplo, wo* incluiría todos los resultados de búsqueda wool de woven y. Actualmente, el SDK de Flutter no admite búsquedas de sufijos.
En el siguiente ejemplo, consultamos los campos Rug.pattern y Rug.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*"]);
Detalles del tokenizador de búsqueda de texto completo
Los índices de búsqueda de texto completo (FTS) admiten:
Búsquedas de palabras con coincidencias booleanas, no búsquedas de relevancia.
Los tokens no distinguen entre mayúsculas y minúsculas ni entre signos diacríticos.
Los tokens solo pueden constar de caracteres ASCII y del suplemento latino1 (idiomas occidentales).
Todos los demás caracteres se consideran espacios en blanco. Las palabras separadas por un guion (-), como el texto completo, se dividen en dos tokens.
Para obtener más información sobre las características del índice FTS, consulte la referencia de API para RealmIndexType.
Ordenar resultados
Ordene los resultados de la consulta utilizando el operador SORT() del query() lenguaje de consulta Realm en el argumento del método.
Tenga en cuenta que no se pueden usar consultas parametrizadas en las cláusulas RQL SORT(). En su lugar, utilice cadenas o interpolación de cadenas.
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'
Limitar los resultados
Limita los resultados de la consulta utilizando el operador LIMIT() del Realm Query Language en el argumento del método query().
Tenga en cuenta que no se pueden usar consultas parametrizadas en las cláusulas LIMIT() de RQL. En su lugar, utilice cadenas o interpolación de cadenas.
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);