Tiempo estimado para completar: 30 minutos, dependiendo de su experiencia con C++
El SDK de dispositivos Atlas para C++ permite almacenar y sincronizar datos entre teléfonos, tabletas, wearables o dispositivos IoT. Este tutorial se basa en la aplicación de plantilla de C++. cpp.todo.flex, que ilustra la creación de una aplicación GUI de terminal de lista de tareas pendientes creada con
FTXUIEsta aplicación permite a los usuarios:
Registrar su correo electrónico como una nueva cuenta de usuario.
Sign in to their account with their email and password (and sign out later).
Ver, crear, modificar y eliminar sus propias tareas.
View all tasks, even where the user is not the owner.
La aplicación de plantilla también proporciona un interruptor que simula el dispositivo en modo sin conexión. Este interruptor permite probar rápidamente la sincronización del dispositivo en el simulador, simulando que el usuario no tiene conexión a internet. Sin embargo, es probable que este interruptor se elimine en una aplicación de producción.
This tutorial builds on the Template App. You will add a new priority field to the existing Item model and update the Flexible Sync subscription to only show items within a range of priorities.
Objetivos de aprendizaje
Este tutorial ilustra cómo adaptar la aplicación de plantilla a sus necesidades. Dada la estructura actual de la aplicación, no es necesario realizar este cambio.
En este tutorial aprenderás a:
Actualice un modelo de objetos de C++ con un cambio ininterrumpido.
Actualizar una suscripción de sincronización de dispositivos.
Add a queryable field to the Device Sync configuration on the server to change which data is synchronized.
Tip
Si prefieres comenzar con tu propia aplicación en lugar de seguir un tutorial guiado, consulta la Guía rápida de C++. Incluye ejemplos de código que se pueden copiar y la información esencial que necesitas para configurar un backend de Atlas App Services.
Requisitos previos
Asegúrate de tener instalado el software necesario. La aplicación de plantilla de C++ presupone que tienes:
Versión deCMake. 3o más reciente.25
C++ 17 o más reciente.
Este tutorial comienza con una aplicación de Plantilla. Necesitas una Cuenta de Atlas, una clave API y App Services CLI para crear una aplicación de plantilla.
Para obtener más información sobre cómo crear una cuenta de Atlas, consulte la sección Primeros pasos con Atlas. Para este tutorial, necesita una cuenta de Atlas con un clúster de nivel gratuito.
También necesita una clave API de Atlas para la cuenta de MongoDB Cloud con la que desea iniciar sesión. Debe ser propietario del proyecto para crear una aplicación de plantilla mediante la CLI de App Services.
Para aprender más sobre cómo instalar App Services CLI, consulta Instalar App Services CLI. Después de instalar, ejecuta el comando login utilizando la clave API de tu proyecto Atlas.
Comience con la plantilla
This tutorial is based on the C++ Sync Template App named cpp.todo.flex. We start with the default app and build new features on it.
Para obtener más información sobre las aplicaciones de plantilla, consulte Aplicaciones de plantilla.
Si aún no tiene una cuenta Atlas, regístrese para implementar una aplicación de plantilla.
Siga el procedimiento descrito en la guía Crear una aplicación de servicios de aplicaciones y seleccione Create App from TemplateSeleccione la plantilla Real-time Sync. Esto crea una aplicación de Servicios de Aplicaciones preconfigurada para usarla con uno de los clientes de la plantilla de Sincronización de Dispositivos.
Después de crear una aplicación plantilla, la Interfaz de Usuario muestra un modal etiquetado como Get the Front-end Code for your Template. Este modal proporciona instrucciones para descargar el código cliente de la aplicación plantilla como un archivo .zip o para usar App Services CLI y obtener el cliente.
La aplicación de plantilla de C++ aún no está disponible para descargar en la interfaz de App Services. Usa la CLI o clona el repositorio desde GitHub para obtener el código del cliente.
El comando appservices apps create configura el backend y crea una aplicación de plantilla de C++ para que la uses como base para este tutorial.
Ejecute el siguiente comando en una ventana de terminal para crear una aplicación llamada "MyTutorialApp" que se implementa en la región US-VA con su entorno configurado en "desarrollo" (en lugar de producción o control de calidad).
appservices app create \ --name MyTutorialApp \ --template cpp.todo.flex \ --deployment-model global \ --environment development
El comando crea un nuevo directorio en su ruta actual con el mismo nombre que el valor del indicador --name.
Puedes bifurcar y clonar un repositorio de GitHub que contenga el código del cliente de Device Sync. El código del cliente en C++ está disponible en https://github.com/mongodb/template-app-cpp-todo.
Si usas este proceso para obtener el código del cliente, debes crear una aplicación de plantilla para usar con el cliente. Sigue las instrucciones en Crear una aplicación de plantilla para usar la Interfaz de Usuario de Atlas App Services, los App Services CLI o la API de Administración para crear una aplicación de plantilla Device Sync.
Explora la aplicación plantilla
Abre la aplicación
Open the frontend client code in your preferred IDE.
Si clonaste el cliente desde un repositorio de GitHub, debes insertar manualmente el ID de la aplicación de App Services en el lugar correspondiente de tu cliente. Sigue las instrucciones Configuration del cliente README.md para saber dónde insertar el ID de la aplicación.
Compila la aplicación
Cree un directorio para compilar la aplicación. Para mayor comodidad, el
.gitignoreempaquetado con la aplicación de plantilla ignora el directoriobuilddentro del directorio del cliente. Navegue al directorio de compilación.mkdir build && cd build Use CMake para crear el Makefile. Suponiendo que compila desde un directorio
builddentro del directorio del cliente:cmake ../ Use CMake to build the app executable. This takes a few moments as it installs the dependencies and compiles the executable.
cmake --build .
Explorar la estructura de la aplicación
Tómese unos minutos para explorar cómo está organizado el proyecto mientras CMake compila el ejecutable.
You won't work directly with these files during this tutorial, but they contain code that demonstrates using the C++ SDK:
Archivo | Propósito |
|---|---|
| Utilice la librería Para obtener más información sobre cómo puede personalizar la configuración de su aplicación, consulte: Conectarse a un backend de Atlas App Services. Este código también configura el |
| Lógica para registrar un usuario de correo electrónico/contraseña, iniciar o cerrar sesión y mostrar un mensaje de error cuando ocurren errores de autenticación. |
En este tutorial, trabajarás con los siguientes archivos:
Archivo | Propósito |
|---|---|
| Definimos el objeto |
| Administrar el estado de la aplicación para la vista de Inicio. |
| Contiene definiciones importantes para el controlador de vista de inicio. |
| Implements the Home view. This is the view where a logged-in user can work with the app. |
| Contiene definiciones importantes para Device Sync y operaciones de base de datos. |
| Implementa algunas operaciones de Device Sync y base de datos, como crear elementos, cambiar suscripciones de consultas de Device Sync y manejar errores de sincronización. |
Ejecutar la aplicación
Sin modificar el código, debería poder ejecutar la aplicación en la terminal. Pase la ruta a atlasConfig.json como argumento al ejecutar la aplicación:
./sync_todo /path-to-file/atlasConfig.json
Ejecute la aplicación, registre una nueva cuenta de usuario y luego agregue un nuevo elemento a Su lista de tareas.
Tip
Expande la ventana del terminal, si es necesario.
La parte superior de la pantalla de inicio contiene una fila de botones y un interruptor para ocultar las tareas completadas. Si la ventana de la terminal es demasiado pequeña, las etiquetas de texto de los botones no se mostrarán. Para ver las etiquetas, amplíe la ventana de la terminal y FTXUI renderizará el contenido para que se ajuste a la ventana más grande.
Comprueba el Backend
Inicia sesión en Atlas App Services. En la pestaña Data Services, haz clic en Browse Collections. En la lista de bases de datos, busca y expande la base de datos todo y luego la colección Item. Debería ver el documento que creó en esta colección.
Modificar la aplicación
Agregar una nueva propiedad
Agregar una propiedad al modelo
Ahora que ha confirmado que todo funciona correctamente, puede añadir cambios. En este tutorial, añadirá una propiedad priority a cada Item para poder filtrar los elementos por prioridad.
En una aplicación de producción, podrías añadir una enumeración PriorityLevel para restringir los valores posibles. En este tutorial, usaremos una propiedad numérica para agilizar el trabajo con el framework de la interfaz de usuario.
Para ello siga estos pasos:
Abre el código del cliente en tu IDE preferido.
In the
state/directory, ppen theitem.hppfile.Agregue la siguiente propiedad a la estructura
Item:int64_t priority; Agregue la nueva propiedad
priorityaREALM_SCHEMA():REALM_SCHEMA(Item, _id, isComplete, summary, owner_id, priority) El modelo
Itemahora debería parecerse a:namespace realm { struct Item { realm::primary_key<realm::object_id> _id{realm::object_id::generate()}; bool isComplete; std::string summary; std::string owner_id; int64_t priority; }; REALM_SCHEMA(Item, _id, isComplete, summary, owner_id, priority) } // namespace realm
Agregar un elemento a la interfaz de usuario para establecer la prioridad
In the
statedirectory, go tohome_controller_state.hpp. Add a newintproperty under the existingnewTaskIsCompleteproperty. Then, add astatic const intto store the default int value for this property.The
HomeControllerStatestruct may now resemble:struct HomeControllerState { static const int DEFAULT_TASK_PRIORITY = 3; // Used for creating a new task. std::string newTaskSummary; bool newTaskIsComplete{false}; int newTaskPriority{DEFAULT_TASK_PRIORITY}; ...more code here... }; In the
controllersdirectory, go tohome_controller.hpp. This controller renders the main view of the app.Import the string and vector libraries:
Cree un arreglo de etiquetas de string para el nuevo elemento de Interfaz de Usuario de prioridad:
std::vector<std::string> priorityLevelLabels = { "Severe", "High", "Medium", "Low" }; Siguiendo en el directorio
controllers, vaya ahome_controller.cpp. Aquí es donde añadimos un elemento de interfaz de usuario para permitir al usuario establecer la prioridad del elemento. FTXUI ofrece dos elementos de IU que puedes usar para esta funcionalidad:RadioboxoDropdown. En este tutorial, utilizaremosDropdown, pero puedes preferirRadioboxsi no te agrada cómo la IU renderiza el menú desplegable.Agrega esta nueva entrada de elemento de Interfaz de Usuario después de la línea
auto newTaskCompletionStatus:auto newTaskPriorityDropdown = ftxui::Dropdown( &priorityLevelLabels, &_homeControllerState.newTaskPriority ); En el cierre de la función
auto saveButton, pasa la selección de prioridad de tarea a la llamada de función_dbManager.addNew():_dbManager.addNew( _homeControllerState.newTaskIsComplete, _homeControllerState.newTaskSummary, _homeControllerState.newTaskPriority); Y luego agregue una línea para restablecer la selección de prioridad al valor predeterminado:
_homeControllerState.newTaskPriority = HomeControllerState::DEFAULT_TASK_PRIORITY; Add the dropdown selector to the
auto newTaskLayoutthat sets the layout for the interactive elements in the item row container:auto newTaskLayout = ftxui::Container::Horizontal( {inputNewTaskSummary, newTaskCompletionStatus, newTaskPriorityDropdown, saveButton}); Esta sección de su código deberá ahora parecerse a:
auto newTaskCompletionStatus = ftxui::Checkbox("Complete", &_homeControllerState.newTaskIsComplete); auto newTaskPriorityDropdown = ftxui::Dropdown( &priorityLevelLabels, &_homeControllerState.newTaskPriority); auto saveButton = ftxui::Button("Save", [this] { _dbManager.addNew( _homeControllerState.newTaskIsComplete, _homeControllerState.newTaskSummary, _homeControllerState.newTaskPriority); _homeControllerState.newTaskSummary = ""; _homeControllerState.newTaskIsComplete = false; _homeControllerState.newTaskPriority = HomeControllerState::DEFAULT_TASK_PRIORITY; }); auto newTaskLayout = ftxui::Container::Horizontal( {inputNewTaskSummary, newTaskCompletionStatus, newTaskPriorityDropdown, saveButton}); Finalmente, más abajo en el archivo
home_controller.cpp, agregue el nuevo elemento UI alauto itemListRenderer:inputNewTaskSummary->Render() | ftxui::flex, newTaskCompletionStatus->Render() | ftxui::center, newTaskPriorityDropdown->Render(), saveButton->Render(), Esto representa el nuevo elemento justo antes del botón Guardar en la interfaz de usuario.
Guarda la nueva propiedad en la base de datos
En el directorio
managers, vaya adatabase_manager.hpp. Actualice la firma de la funciónaddNew()para incluir elint newItemPriorityque pasamos desdehome_controller.cpp:void addNew( bool newItemIsComplete, std::string newItemSummary, int newItemPriority); Now go to
database_manager.cpp, and update theaddNew()implementation. Addint newItemPropertyto the function arguments:void DatabaseManager::addNew( bool newItemIsComplete, std::string newItemSummary, int newItemPriority) { ...implementation... } Add a new line in the function to set the value of the
priorityproperty when we save theItemto the database:.priority = newItemPriority Su implementación
addNew()ahora debería parecerse a:void DatabaseManager::addNew(bool newItemIsComplete, std::string newItemSummary, int newItemPriority) { auto item = realm::Item { .isComplete = newItemIsComplete, .summary = std::move(newItemSummary), .owner_id = _userId, .priority = newItemPriority }; _database->write([&]{ _database->add(std::move(item)); }); }
Ejecutar y probar
En este punto, compile y ejecute la aplicación nuevamente. En tu directorio de compilación, recompila el ejecutable con los cambios realizados:
cmake --build .
Y ejecuta la aplicación:
./sync_todo /path-to-file/atlasConfig.json
Inicia sesión con la cuenta que creaste anteriormente en este tutorial. Verás el elemento que creaste. Agrega un nuevo elemento y verás que ahora puedes establecer la prioridad. Selecciona High como prioridad y guarda el elemento.
Ahora, regrese a la página de datos del Atlas en su navegador y actualice la Item colección. Debería ver el nuevo elemento con el priority campo agregado y configurado en 1. El elemento existente no tiene el priority campo.

Nota
¿Por qué no se rompió esta sincronizar?
Agregar una propiedad a un objeto de cliente SDK no es un cambio disruptivo y, por lo tanto, no requiere un restablecimiento del cliente. La aplicación de plantilla tiene el modo de desarrollo habilitado, por lo que los cambios en el objeto de cliente se reflejan automáticamente en el esquema del lado del servidor. Para obtener más información, consulta Modo de desarrollo y Actualizar tu modelo de datos.
Cambiar la suscripción
En el archivo database_manager.cpp del directorio managers, creamos la suscripción de Sincronización Flexible que define qué documentos sincronizamos con el dispositivo y la cuenta del usuario. De forma predeterminada, nos suscribimos a todos los elementos. Puedes ver los elementos creados por otros usuarios, pero las reglas del servidor impiden escribir en ellos. Puedes ver esta lógica en el bloque donde creamos la suscripción inicial. Si no hay suscripciones al abrir la aplicación, añadimos una suscripción para todos los objetos Item:
_database->subscriptions().update([this](realm::mutable_sync_subscription_set& subs) { // By default, we show all items. if (!subs.find(_allItemSubscriptionName)) { subs.add<realm::Item>(_allItemSubscriptionName); } }).get();
En la función toggleSubscriptions(), cambiamos la suscripción según su estado actual. En la interfaz de usuario, el usuario puede alternar entre mostrar todos los elementos o solo los suyos. Dentro de esta función, busque la lógica _myItemSubscriptionName. Si aún no existe una suscripción para este nombre, la aplicación agrega una a todos los documentos donde la propiedad owner_id coincida con el ID del usuario autenticado.
For this tutorial, we want to maintain that, but only sync Items that are marked as "High" or "Severe" priority.
This is why we used an int64_t for the priority property, and labeled the priority levels in the UI from most to least important. The highest priority (severe) has a value of 0, and the lowest priority (low) has a value of 3. We can make direct comparisons between a number and the priority property.
Update the subscription
Para cambiar la suscripción, vaya al managers directorio y abra el database_manager.cpp archivo. Actualice la consulta para incluir los documentos con prioridad igual o inferior 1 a. Esto solo debe incluir elementos con prioridad "Severa" ()0 o "Alta" ().1
if (!subs.find(_myItemSubscriptionName)) { subs.add<realm::Item>( _myItemSubscriptionName, [&](auto &item){ return item.owner_id == _userId && item.priority <= 1; } ); }
Ejecutar y probar
Ejecute la aplicación de nuevo. Inicie sesión con la cuenta que creó anteriormente en este tutorial. En el cuadro Subscription, pulse el botón Switch to
Mine. Tras un momento inicial, cuando el SDK vuelva a sincronizar la colección de documentos, solo verá el nuevo elemento de alta prioridad que creó. Es posible que tenga que mover el ratón o usar las teclas de flecha para que la interfaz de usuario se vuelva a mostrar con los nuevos elementos sincronizados en segundo plano.
El documento de Item que creaste inicialmente no aparece en el dispositivo porque no tiene un campo priority. Si deseas que este Item se sincronice con el dispositivo, puedes editar el documento en la interfaz de usuario de Atlas y agregar un valor para el campo priority.
Tip
Cambiar suscripciones con el modo de desarrollador habilitado
In this tutorial, when you change the subscription and query on the priority field for the first time, the field is automatically added to the Device Sync Collection Queryable Fields. This occurs because the template app has Development Mode enabled by default. If Development Mode was not enabled, you would have to manually add the field as a queryable field to use it in a client-side Sync query.
Para obtener más información, consulte Campos consultables.
Si desea probar la funcionalidad con más detalle, puede crear elementos con diferentes prioridades. Verá que un nuevo elemento con menor prioridad aparece brevemente en la lista de elementos y luego desaparece. El gestor de errores de sincronización proporciona un mensaje que describe este comportamiento:
A sync error occurred. Message: "Client attempted a write that is not allowed; it has been reverted"
En este escenario, el SDK crea el elemento localmente, lo sincroniza con el backend y luego revierte la escritura porque no cumple con las reglas de suscripción.
Nota
Known UI Issue
If the error modal displays, and you move your mouse over the item list in the terminal prior to dismissing the error modal, the UI rendering breaks. This is related to limitations with the FTXUI library. If this occurs, quit the app using ctrl + c, and re-run it. You can avoid this issue by using the enter key to press the Dismiss button in the error modal before moving the mouse.
Conclusión
Agregar una propiedad a un objeto SDK existente es un cambio no disruptivo, y el Modo de desarrollo asegura que el cambio de esquema se refleje del lado del servidor.
¿Qué es lo próximo?
Lea nuestra documentación del SDK de C++.
Find developer-oriented blog posts and integration tutorials on the MongoDB Developer Hub.
Únase a las comunidades de MongoDB en Reddit o Stack Overflow para aprender de otros desarrolladores y expertos técnicos de MongoDB.
Explore proyectos de ingeniería y ejemplos proporcionados por expertos.
Nota
Share Feedback
¿Cómo te fue? Usa el Rate this page widget en la parte inferior derecha de la página para evaluar su efectividad. O reporta un problema en el repositorio de GitHub si tuviste algún problema.