Prácticamente todas las organizaciones necesitan registrar y recuperar datos de usuarios. Con frecuencia, estos datos de usuario son permanentes, como las cuentas de usuario con configuraciones definidas, historiales y preferencias. Con la misma frecuencia, los datos son transitorios, como en el caso de las sesiones anónimas con actividad reciente. En ambos casos, la organización necesitará un almacén de perfiles de usuario/almacén de sesiones para persistir y consultar los datos. Como este tipo de datos es la base de muchas aplicaciones en la mayoría de las organizaciones, es imperativo que el diseño de la base de datos de perfiles de usuario sea eficiente, disponible y escalable. Este post sobre cómo almacenar las preferencias de los usuarios en una base de datos explora un sistema de este tipo.
Vamos a ver un servicio de almacenamiento de perfiles (REST API) utilizando Couchbase como base de datos con un modelo de datos de usuario que juega con los puntos fuertes de Couchbase. Comenzaremos con todos los datos en un documento. Luego veremos cómo y por qué podríamos normalizar este documento en documentos separados y la lógica detrás de los cambios. Todo esto en la perspectiva de lo que funcionará mejor para el modelo de datos de perfil de usuario y cómo planeamos utilizar los poderes de Couchbase Server.
Definición del servicio de perfil de usuario
Empecemos por definir el servicio de ejemplo y sus parámetros. Aquí están los parámetros de diseño que me di para este proyecto:
- Será el almacén de perfiles autorizado para todos los microservicios de una empresa ficticia orientados al cliente y expondrá una API REST para soportar operaciones CRUD contra los datos.
- La API será versionada con funcionalidad retenida y obsoleta de acuerdo con el documento de diseño.
- El objetivo de tiempo de actividad es del 99,999% o superior.
- Ser capaz de configurar los perfiles de usuario para que se conserven durante X años después de su último inicio de sesión y, preferiblemente, la base de datos deberá gestionar la eliminación de los datos de la cuenta junto con la configuración de la aplicación del tiempo de vida (TTL) en los objetos de cada usuario".
- El servicio debería ser capaz de realizar un mínimo de 50.000 autenticaciones y 10.000 búsquedas de perfiles de usuario principales por segundo en instancias de AWS de tamaño relativamente modesto.
Definición de los servicios expuestos por la API REST
Es necesario empezar por mapear cómo se utilizarán los datos. Las interfaces que expondrá mi servicio y cuáles se utilizarán más y menos. Esto me ayudará a saber cómo diseñar mejor mis documentos. Couchbase me permite diseñar un esquema de documentos basado en cómo, cuándo y la frecuencia en la que la aplicación usará los datos y no en cómo la base de datos los almacenará, como podrías estar forzado a hacer en un RDBMS.
He aquí algunos ejemplos de métodos que uno puede tener para este servicio. No voy a enumerarlos todos y perder el tiempo, pero usted consigue la idea.
- getUserProfile(userID) - Obtiene todos los objetos del usuario en la base de datos. Se leerá en una matriz de la clave establecida patrón de nombre de objeto (por ejemplo, ) y luego hacer una operación de obtención masiva en todos los objetos del usuario.
- getSecurityQuestions(userID) - Comprueba en el documento login-info que el usuario está habilitado y si es así, devuelve el documento de preguntas de seguridad del usuario. Si el usuario está deshabilitado, devolverá un error.
- setSecurityQuestions(userID) - escribe el documento de preguntas de seguridad del usuario.
- authorizeUser(userID, passwordHash, IP) - obtiene el documento de autenticación del usuario, llama a la función isEnabled y si la cuenta está habilitada comprueba si la contraseña coincide. Si coinciden, actualiza el documento con la IP y el último inicio de sesión.
- isEnabled(userID) - comprueba el documento login-info del usuario para ver si la cuenta está habilitada o no en el sistema. Devolverá verdadero o falso.
Encontrará una lista completa de los métodos en la última entrada del blog que trata sobre el desarrollo de la aplicación y el código de ejemplo.
El documento inicial del usuario principal
He aquí un ejemplo de documento de perfil de usuario con el que podría empezar y que recoge todos los datos que necesitará mi servicio y que sería una forma perfectamente válida de hacerlo.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
clave : hernandez94 { "nombre de usuario" : "hernandez94", "nombre" : "Jennifer", "middleName" : "Maria", "apellido" : "Hernández", "direcciones" : [ { "tipo" : "home", "addr1" : "Avenida Crisanto 1929", "dirección" : "Apt 123", "addr3" : "c/o J. Hernandez", "ciudad" : "Mountain View", "estado" : "CA", "país" : "USA", "pcode" : "94040" }, { "tipo" : "trabajo", "addr1" : "2700 W El Camino Real", "addr2" : "Suite #123", "ciudad" : "Mountain View", "estado" : "CA", "país" : "USA", "pcode" : "94040" }, { "tipo" : "facturación", "addr1" : "Apartado de correos 123456", "ciudad" : "Mountain View", "estado" : "CA", "país" : "USA", "pcode" : "94041" } ], "emails" : [ { "tipo" : "trabajo", "addr" : "work@email.com" }, { "tipo" : "personal", "addr" : "personal@email.com", "primario" : verdadero } ], "teléfonos" : [ { "tipo" : "trabajo", "num" : "+12345678900" }, { "tipo" : "móvil", "num" : "+12345678901" } ], "fecha de creación" : "2016-08-01 15:03:40", "lastlogin": "2016-08-01 17:03:40", "pword": "app-hashed-password", "loc": "IP o fqdn", "activado" : verdadero, "sec-preguntas" : [ { "question1" : "La pregunta de seguridad 1 va aquí", "respuesta" : "La respuesta a la pregunta de seguridad 1 va aquí" }, { "question2" : "La pregunta de seguridad 2 va aquí", "respuesta" : "La respuesta a la pregunta de seguridad 2 va aquí" }, { "question3" : "La pregunta de seguridad 3 va aquí", "respuesta" : "La respuesta a la pregunta de seguridad 3 va aquí" } ], "sec-roles" : [101, 301, 345], "doc-type" : "usuario" } |
Este documento ocupa alrededor de 1,41kb y aún no se han rellenado todos los datos. Así que este documento podría hacerse más grande dependiendo del usuario. Si tienes desarrolladores o eres un desarrollador al que le gusta añadir y añadir y añadir datos a un documento o tabla, entonces podría crecer mucho a lo largo de la evolución de tu aplicación/servicio. Veamos cómo optimizar este documento para cómo y cuándo la aplicación utilizará estos datos.
Unas breves palabras sobre el acceso a datos en Couchbase
Para las partes principales de este servicio necesito la potencia y el rendimiento de acceder a mis datos a través de una clave y consultar los datos lo menos posible. Sin rehacer mi otra entrada en el blog sobre el acceso a los datos demasiado, Couchbase tiene múltiples formas de acceder a los datos. Si proporcionas el ObjectID del objeto(s) que quieres, tu aplicación puede leer y escribir esos objetos excepcionalmente rápido desde la caché gestionada del Servicio de Datos.
Si quieres hacer una consulta usando el lenguaje N1QL de Couchbase (~98% compatible con ANSI 92 SQL) eso significa que tienes una pregunta de los datos y eso se puede hacer también a través del Servicio de Consulta. Por su naturaleza de tener que hacer más trabajo, la consulta es menos performante que trabajar con datos por ObjectID. Es la diferencia entre tener una pregunta (consulta) y conocer ya la respuesta (ObjectID). (Para más información sobre por qué digo esto, consulte mi otra entrada del blog sobre "Cómo las necesidades funcionales y de rendimiento determinan el acceso a los datos en Couchbase“).
Para este diseño de esquema de base de datos de perfil de usuario, nos aseguraremos de que nuestros objetos puedan ser accedidos eficientemente por ambos medios cuando sea necesario. Los "caminos calientes" de la aplicación serán accedidos por ObjectID tanto como podamos, pero también haremos consultas cuando sea necesario. Tenemos que cumplir los requisitos establecidos anteriormente en este documento.
Optimización del documento principal de usuario
En el diseño de un modelo de datos de usuario para este servicio, tenemos algunas opciones disponibles que son un tanto exclusivas de Couchbase y de cómo escala, rinde y gestiona la memoria. Dado que todos los objetos son elegibles para ser guardados en la caché gestionada del Servicio de Datos, queremos que el modelo de datos de documentos y el patrón de claves utilizado por nuestro servicio sea lo suficientemente flexible como para que los datos que necesitamos con frecuencia estén en la caché gestionada y los datos utilizados con poca frecuencia puedan estar simplemente en el disco, lo cual está bien. Otras bases de datos de documentos NoSQL pueden hacer que pongas todo en un documento y luego consultes esos datos. La consulta con N1QL también está disponible en Couchbase, y la usaremos para propósitos específicos. De nuevo, la arquitectura de Couchbase con su modelo de datos flexible y su caché gestionada integrada nos permite elegir dónde y cómo queremos utilizar este poder en nuestro beneficio.
Utilizaré un patrón de claves y un modelo de datos normalizado, cuando tenga sentido. Haciendo esto, tenemos la capacidad de sólo leer y escribir los datos exactos que necesitamos, cuando los necesitamos y como los necesitamos, pero cuando necesitamos consultar datos con N1QL, podemos hacer eso también. Algunos de estos patrones de diseño pueden parecerte extraños, pero así es como podrás ejecutar y escalar Couchbase fácilmente para alcanzar decenas o cientos de miles de operaciones por segundo... o incluso más. En blogs posteriores, repasaré cómo queremos consultar algunos datos para hacer analíticas o algo más adelante.
De nuevo, quiero intentar diseñar los documentos en torno a la aplicación obteniendo sólo los datos que necesita, exactamente cuando los necesita y leyéndolos con la clave y no consultando. Sin necesidad de índices, vistas, uniones, etc. Así es como obtendrás el mejor rendimiento y escalabilidad con Couchbase.
El documento Login-Info
He separado la información de inicio de sesión del usuario en un documento propio por varias razones, y utilizaré esta misma filosofía para otros documentos más adelante.
- La información de inicio de sesión se necesita con bastante frecuencia, ya que los usuarios se autentican mucho en nuestra aplicación, y cuando el servicio necesita estos datos, no necesita el resto de la información del usuario la mayoría de las veces. Sí, Couchbase tiene edición de sub-documentos, pero como la mayoría de las bases de datos NoSQL, en el back-end el documento sigue siendo reensamblado y transmitido en su totalidad, por ejemplo, la replicación entre clusters (XDCR). Prefiero evitar esto siempre que puedo.
- Preferiría que el servicio sólo devolviera de la base de datos a la aplicación un documento de 141 bytes que todos los 1,41k o más del documento principal. La edición de subdocumentos puede mitigar esto, pero no las dos razones siguientes.
- Por rendimiento, prefiero mantener una tonelada de documentos de 141 bytes en la caché gestionada en lugar de los más grandes cuando, de nuevo, no siempre necesito el documento completo. Mantener todo el documento en la caché puede no importar demasiado cuando tengo 100.000 usuarios y sólo estoy haciendo 1000 operaciones por segundo, pero cuando tengo millones de usuarios y tengo que hacer 10s si no 100s de miles de operaciones por segundo y necesito mantener su rendimiento, se suma. Tanto en rendimiento como en recursos monetarios, concretamente RAM.
- Hacer esto también significa para los visitantes regulares de mi servicio, que su documento debe estar siempre en la caché gestionada para que obtengan el mejor rendimiento.
También quiero actualizar este documento con la fecha actual en el valor lastlogin y con la IP desde la que entraron cada vez que el usuario se conecta con éxito. Esto no es rastreado por Couchbase automáticamente, pero lo necesito para propósitos de análisis de negocio y para eliminar usuarios que no han iniciado sesión durante mucho tiempo. En este caso, sólo estoy actualizando un documento muy pequeño.
Dado que no es crítico para las operaciones diarias de autenticación de usuarios, para el requisito de eliminar usuarios que no han iniciado sesión en el sistema en X años, utilizaremos esto para otra entrada del blog.
También hay una entidad en el documento llamada "enabled" que se puede utilizar en el servicio para ver si el usuario tiene permiso para iniciar sesión o no.
|
1 2 3 4 5 6 7 8 9 10 |
clave : inicio de sesión-información::hernandez94 { "lastlogin": "2016-08-01 15:03:40", "pword": "app-hashed-password", "loc": "IP o fqdn", "activado" : verdadero, "doc-type" : "login-info", "nombre de usuario" : "hernandez94" } |
Una parte crítica aquí es la clave del documento. Este tipo de patrón clave es algo que es consistente en mi aplicación como verás más adelante. Puedo fácilmente hacer que la aplicación concatene eso con el nombre de usuario único. Esa clave es importante ya que no tendré que consultar este documento en Couchbase, tengo la clave. Conocer la clave significa que el SDK de Couchbase ya sabe la respuesta a la pregunta "¿Dónde está este dato que estoy buscando?", mientras que consultar una base de datos es hacer esa pregunta a la base de datos y usar la potencia de la base de datos (y todo lo que eso conlleva) para encontrar la respuesta y devolver los datos. Así que conocer la clave y decirle a la base de datos que lea/escriba ese objeto, especialmente si ya está en la caché gestionada, será extremadamente rápido con Couchbase. Incluso si el objeto está en el disco y no en la caché gestionada, será rápido y se colocará en la caché gestionada para que esté listo para su uso en consultas posteriores. La gestión de la caché está detrás de las escenas y no es algo que tu aplicación tenga que saber.
También estaba pensando en separar la entidad "enabled" del documento JSON en su propio objeto de par clave/valor ya que Couchbase soporta esto. Estaba pensando que podría haber bastantes lugares en los que sólo necesitaría saber si el usuario está habilitado en el sistema o no. Aunque es posible, decidí no hacerlo porque ya estaba empezando a normalizar mucho los datos y tengo que parar en algún sitio. Este es uno donde por el bien de la complejidad, tenía sentido dejarlo estar.
Una de las otras cosas a notar en este nuevo documento es que agregué las entidades doc-type y username al esquema del documento. También las verás en todos los demás documentos. La razón para el tipo de documento es que puedo hacer una indexación secundaria más tarde. El nombre de usuario es para la indexación, sino también porque entonces puedo hacer JOINs en N1QL entre cualquiera de estos documentos y el nuevo documento principal verás que terminamos con. En partes posteriores de esta serie, usted verá más acerca de por qué es importante y cómo lo usamos para nuestra ventaja.
Para recapitular, separamos este fragmento de información del documento principal del usuario en un documento más pequeño por varias buenas razones. Necesitamos el documento a menudo, lo mantenemos pequeño para lecturas/escrituras eficientes y, por lo tanto, debería mantenerse en la caché gestionada para la mayor parte de los usuarios que nos importan. Además, como podemos obtener el objeto por su clave, no tenemos que consultar la base de datos, por lo que las búsquedas son muy rápidas. También añadimos valores al documento JSON para facilitar la consulta más adelante.
Documento sobre cuestiones de seguridad
Creé el documento de preguntas de seguridad, ya que a diferencia del documento de información de inicio de sesión que se necesita muy a menudo, estos datos se necesitarán muy raramente. Las veces que el servicio necesita esta información, específicamente no necesita el resto de la información del usuario. Por lo tanto, tenía sentido dividirlo en su propio objeto y añadir una clave que la aplicación pudiera concatenar fácilmente para obtener el documento por clave. También convertí esto de una matriz a cada pregunta siendo su propio objeto. Por ejemplo, pregunta1.pregunta o pregunta2.respuesta y en el código de mi aplicación puedo generar aleatoriamente un número entre 1 y 3 y luego utilizar una API de subdocumento para obtener sólo esa pregunta. También tendría la opción de mostrar las tres preguntas dependiendo de cómo funcione mi aplicación. Me gusta tener opciones.
|
1 2 3 4 5 6 7 8 9 |
clave : sec-preguntas::hernandez94 { "question1" : { "pregunta" : "La pregunta de seguridad 1 va aquí", "respuesta" : "La respuesta a la pregunta de seguridad 1 va aquí" }, "question2" : { "pregunta" : "La pregunta de seguridad 2 va aquí", "respuesta" : "La respuesta a la pregunta de seguridad 2 va aquí" }, "question3" : { "pregunta" : "La pregunta de seguridad 3 va aquí", "respuesta" : "La respuesta a la pregunta de seguridad 3 va aquí" }, "doc-type" : "sec-preguntas", "nombre de usuario" : "hernandez94" } |
Además, debido a que el documento no se utiliza muy a menudo es posible que este documento podría caer fuera de la caché administrada y no me importa. Los usuarios lo usan con tan poca frecuencia, que si hay un pequeño impacto en el rendimiento por ir al disco a buscarlo, ¡que se aguante usuario! No estoy pagando para mantener todos estos datos en la RAM porque usted no puede recordar algo acerca de su cuenta de usuario.
Documento de funciones de seguridad del usuario
Quería tener una lista de roles de seguridad para asociar a un usuario. Como muchas otras cosas, cuando necesito esta información, no necesito otra información sobre el usuario. Probablemente tendré otro documento en algún lugar definiendo los roles de seguridad a los que se asignan.
|
1 2 3 4 5 6 7 |
clave : usuario-sec-papeles::hernandez94 { "sec-roles" : [101, 301, 345], "doc-type" : "user-roles", "nombre de usuario" : "hernandez94" } |
Documento de funciones de seguridad
Dispondré de otra serie de documentos en los que se definirán las funciones de seguridad a las que corresponden.
|
1 2 3 4 5 6 7 |
clave : sec-papeles::101 { "nombre" : "Administrador", "descr" : "Administradores del servicio", "doc-type" : "sec-role" } |
Esto es interesante, ya que podría meterme en problemas más adelante. Debido a que este documento podría ser leído con bastante frecuencia, podría crear un punto caliente dependiendo de la frecuencia con la que mi aplicación lo utilice. He visto un cliente que guardaba la configuración de su aplicación en Couchbase en un documento, pero lo leía como 10.000+ veces por segundo. Mientras que un solo nodo de Couchbase puede manejar eso fácilmente, esto era además de todo su otro tráfico. Así que el único nodo del cluster que tenía este documento estaba saturado. Esto no debería ser un problema aquí, pero es algo a tener en cuenta. Probablemente voy a seguir más adelante con un post sobre cómo se podría solucionar esto, pero 99 veces de cada 100, esto no debería ser un problema. Sólo he visto un punto caliente en Couchbase esta vez y realmente fue un problema de diseño de la aplicación que lo causó.
Correo electrónico, direcciones, teléfonos Documentos
Podrías separar las matrices de email, teléfonos y/o direcciones del documento original dependiendo de cómo tu aplicación utilice los datos. Tal vez tenemos un método getEmail() o getAddress() que se expone como parte de este servicio. El método getMail() tomaría como entrada el nombre de usuario único y sería capaz de construir fácilmente la clave (email-addr::hernandez94) para el documento. Como normalizar en cualquier base de datos, se puede ir demasiado lejos. Así que ten cuidado y hazlo sólo si tienes una razón sólida para hacerlo.
|
1 2 3 4 5 6 7 8 |
clave : teléfonos::móvil::hernandez94 { "doc-type" : "teléfono", "num" : "+12345678900", "tipo" : "móvil", "id" : "hernandez94" } |
Hacer documentos para cada número de teléfono que el usuario tiene como abajo me daría opciones tanto para acceso KV como para acceso N1QL. La siguiente consulta me daría todos los números de teléfono de este usuario y su tipo (por ejemplo, móvil, trabajo, etc.)
|
1 |
SELECCIONE num, tipo DESDE perfiles de usuario DONDE id = "hernandez94" Y doc-tipo = "teléfono"; |
También podría concatenar la clave del documento anterior y obtenerla a través de KV. Esto le da opciones.
El nuevo documento principal
Este es el documento principal. Si los patrones de usuario de mi aplicación lo dictaran, desglosaría cosas como direcciones y teléfonos, pero a efectos de ejemplo he decidido dejarlo así, ya que todos los datos que he dejado aquí son datos que no necesito tan a menudo o que, cuando lo hago, los necesito al mismo tiempo. ¿Podría normalizar más? Sí, por ejemplo, podría desglosar la fecha de creación en un objeto de valor clave, ya que quiero registrarlo, pero muy rara vez lo necesito, pero por el momento esto me lleva a donde tengo que estar. No quiero volverme demasiado loco. Además, cuantos más documentos tenga, más metadatos tendrá también.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
clave : hernandez94 { "nombre" : "Jennifer", "middleName" : "Maria", "apellido" : "Hernández", "direcciones" : [ { "tipo" : "home", "addr1" : "Avenida Crisanto 1929", "dirección" : "Apt 123", "addr3" : "c/o J. Hernandez", "ciudad" : "Mountain View", "estado" : "CA", "país" : "USA", "pcode" : "94040" }, { "tipo" : "trabajo", "addr1" : "2700 W El Camino Real", "addr2" : "Suite #123", "ciudad" : "Mountain View", "estado" : "CA", "país" : "USA", "pcode" : "94040" }, { "tipo" : "facturación", "addr1" : "Apartado de correos 123456", "ciudad" : "Mountain View", "estado" : "CA", "país" : "USA", "pcode" : "94041" } ], "teléfonos" : [ { "tipo" : "trabajo", "num" : "+12345678900" }, { "tipo" : "móvil", "num" : "+12345678901" } ], "fecha de creación" : "2016-08-01 15:03:40", "doc-type" : "usuario" } |
Ejemplo de código Java
Este es un ejemplo de código Java de una operación de obtención masiva para obtener todos los documentos asociados al usuario:
Esto le permite obtener todos los documentos asociados a este usuario muy fácil y rápidamente. Algo así como poner diferentes piezas de datos en diferentes tablas en una base de datos relacional y luego hacer una unión para obtener toda la información. Esto sería MUCHO más rápido que eso.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Grupo grupo = CouchbaseCluster.crear(); Cubo cubo = grupo.openBucket(); Lista foundDocs = Observable .sólo( userID, "sec-questions::" + userID, "login-info::" + userID, "user-sec-roles::" + userID) .flatMap(nuevo Func1<Cadena, Observable>() { @Anular público Observable llame a(Cadena id) { devolver cubo.async().consiga(id); } }) .toList() .toBlocking() .solo(); |
Podría pensar en modificar el código para asegurarme de que tengo todos los documentos cuando termine con esta llamada y si no hacer una lectura de réplica para los documentos que faltan, en caso de que un nodo esté caído, pero ya te haces una idea.
Para más información sobre cómo hacer "bulk gets", por favor consulta la documentación de tu SDK de Couchbase.
Resumen
Couchbase te ofrece una forma diferente de modelar tus datos en contraposición a otras bases de datos de documentos y especialmente a las bases de datos relacionales. Al dividir algunos datos en diferentes documentos, pero relacionados por la información en la clave y el documento, podemos obtener los datos exactos que necesitamos para la aplicación cuando los necesitamos. Mantenemos frescos exactamente los datos que queremos en la caché gestionada que se utiliza a menudo, pero si necesitamos todos los documentos del usuario, podemos hacer una operación masiva en todos ellos muy rápidamente. La última parte importante es el patrón de claves utilizado aquí. De nuevo, acceder a los objetos por clave es la diferencia entre conocer ya la respuesta y tener que hacer una pregunta como en otras bases de datos.
Toda esta charla sobre rendimiento y patrones clave ignora las ocasiones en las que realmente queremos consultar los datos. Cuando tenemos preguntas como "¿Cuántos usuarios tienen un código postal de 98038?". Pero, como he dicho antes, eso lo dejaremos para otra entrada de esta serie.
Muy bien escrito Kirk....esperando ansiosamente la parte II de esta serie.
Hola Kirk, impresionante artículo. Apenas estoy entrando en NoSQL y quiero empezar a usar Couchbase, y este es un gran material de aprendizaje.
Me gusta cómo utiliza las claves de cadena esencialmente como uniones entre documentos. Estoy debatiendo qué hacer en mi escenario más complejo: Digamos que estoy construyendo una aplicación que permite a los usuarios almacenar datos adicionales relacionados con los tweets de Twitter, por ejemplo "guardar este tweet como favorito". Un solo usuario podría tener fácilmente miles de estos favoritos acumulados a lo largo del tiempo. Esencialmente se trata de una relación de muchos a muchos entre Usuarios y Tweets. Siguiendo tu ejemplo, la clave para estos pequeños documentos podría ser: _
En mi escenario, todas estas relaciones son estrictamente privadas para el usuario que las creó. Y todas ellas necesitan ser replicadas en el dispositivo del usuario a través de Couchbase Lite. Por estas razones, ¿sería mejor almacenarlas todas en un único documento para ese usuario, o quizás en documentos fragmentados en función de la hora, el flujo de Twitter, etc.?
Gracias.
Esta es una pregunta difícil, ya que hay pros y contras en ambos sentidos. Si los almacenas todos en un documento, ¿en qué momento un usuario superaría el límite de 20 MB del documento o tendría que arrastrar un gran documento JSON sólo para añadirle un tweet? Por otro lado, si cada tweet está en su propia, entonces usted podría llegar a una situación en la que tiene miles de millones de objetos y almacenar un montón de meta-datos como Couchbase almacena ~ 54 bytes por objeto de datos. Podrías expulsar eso también, pero tendrías un impacto en el rendimiento para ver si un documento existe.
En cualquier caso, lo que yo recomendaría ver son tres posibilidades.
1) Ver si almacenar cada tweet como un objeto, pero entonces la clave sería algo que describo en mi otro objeto modelado blog post funcionaría. http://bit.ly/1Hx3a74
2) Otra opción que he visto utilizado con gran efecto es tener cada tweet en un documento separado, pero luego tener un documento de índice manual por usuario. Así que para obtener los favoritos de ese usuario, coges ese documento que tiene su "index" y en ese documento está la lista de los IDs de los objetos de los tweets que son sus favoritos. si necesitas obtenerlos todos, ahora que tienes la lista de objetos a obtener, usas las operaciones masivas del SDK de Couchbase y obtienes todos o la porción que necesitas. ¿Tiene sentido?
3) Una mezcla de 1 y 2 en función de su caso de uso y del perfil de rendimiento requerido.
Gran artículo. Gracias por la información. Alguien sabe dónde puedo encontrar un espacio en blanco \ "cómo enviar por correo electrónico la solicitud \" para llenar?
Hey jeannie, I
ha podido "enviar la solicitud por correo electrónico" desde este enlace
http://goo.gl/yoGwr2. También me permitía descargar, editar, imprimir, guardar, firmar, enviar por correo electrónico o incluso por fax.
¿Cómo enviar un correo electrónico a quién?
Buen artículo, ¡gracias! Esperando la segunda parte.
Buen artículo.
El modelado de datos de la tienda de perfiles de usuario sólo consideran el uso de Couchbase Server, si hay un consejo sobre el modelado de datos cuando uso Couchbase Server y Couchbase Mobile será útil.
por ejemplo, al utilizar Couchbase Mobile, debemos tener en cuenta la restricción de enrutamiento SG/ACL, la restricción de consulta de CouchbaseLite por map/reduce, etc.
Couchbase Mobile no es mi área de especialización, por lo que dudo que pueda hacer justicia al tema. Sin embargo, voy a pasar esto a los que podrían ser capaces de ayudar y escribir algo para ti. La otra opción para ti, si no lo has hecho ya, es usar los foros de Couchbase para preguntar sobre esto.
También puedes empezar aquí, y publicaremos más formación sobre Couchbase Mobile en las próximas semanas. http://developer.couchbase.com…
Gran artículo Kirk. Información muy detallada. ¿Hay alguna fecha en mente para la parte 2 de este artículo?
Gracias.
[...] ejemplos de cómo podrías utilizar un patrón de ID de objeto estandarizado en tu aplicación, consulta esta y esta entrada de blog que escribí. Incluso si los casos de uso específicos en los blogs no son aplicables a [...]
Cómo bellamente que resolver este problema gracias por compartir hombre sigue así.
Proveedores de embalaje e impresión