2012-02-16 6 views
7

Soy bastante nuevo para objetivar, y que tenía una pregunta rápida para la mejor manera de hacer algo:Relaciones de Objectify: One-to-Many, ¿Puedo hacer esto de manera eficiente?

Digamos que tengo una aplicación que permite a las personas enviar y recibir mensajes (piensa correo electrónico para sencillez). Cuando se carga mi aplicación, no deseo cargar todos los mensajes de cada contacto que haya enviado un mensaje a un usuario determinado. Eso sería un desperdicio. En su lugar, quiero cargar todos los contactos que un usuario tiene mensajes de (lectura o no leída) para que pueda mostrar una lista de los contactos en mi aplicación, y cuando el usuario hace clic en un contacto determinado quiero cargar todos los de los mensajes de ese contacto para mostrar al usuario.

No puedo encontrar una buena forma de hacerlo sin cargar todos los mensajes de una cuenta. Leí el wiki de Objectify en relaciones de varios a uno, y todavía no puedo pensar en una buena manera de hacer esto que no sea extremadamente ineficiente. Parecería que por la forma en que el sitio de Objectify lo recomienda, tendría que cargar todos los mensajes para un usuario dado y luego analizarlos para contactos únicos.

Estoy tratando de utilizar el menor número de App Engine Lee y escribe como sea posible, y donde sea posible Estoy tratando de utilizar cargas fraccionadas en lugar de Lee (coste global para ejecutar mi aplicación es una gran preocupación mía mientras Estoy haciendo esto).

En Objectify, ¿cómo debería estar haciendo esto?

Respuesta

11

Esto se copia de mi respuesta en el Objectify-appengine grupo de Google: https://groups.google.com/forum/?fromgroups#!topic/objectify-appengine/LlOyRJZRbnk

Hay tres opciones principales cuando se trata de "datos de agregación", como lo que describes:

1) Cálmelo cuando lo necesite

Ha concluido, con razón, creo, que esto es demasiado caro.

2) Calcular a intervalos lotes y almacenar este resultado

No muy satisfactorio ya que implica un retraso. Además, no desea peinar toda su base de datos todas las noches.

3) Actualización de la agregación cuando los datos cambian

Este enfoque implica un poco más de trabajo cada vez que cambian los datos, pero es casi seguro que lo que quiere hacer.

Crea algún tipo de colección de contactos para cada usuario. Cuando llega un mensaje, asegúrese de que exista un contacto del remitente para ese destinatario. Quizás también quiera eliminar el contacto cuando el destinatario borre el último mensaje de un remitente.

Tenga cuidado de no tropezar con los límites de velocidad de transacción del grupo de entidades (una escritura por segundo).Me voy a caminar a través de algunas opciones:

1) Se puede almacenar una lista de contactos en cada destinatario:

class Person { 
    @Id Long id; 
    Set<Key<Person>> contacts; 
} 

Esto sería un problema distinto si, por ejemplo, el destinatario recibe el correo de 20 nuevos personas a la vez. Esto es casi seguro una mala idea. Por otro lado, es tremendamente rápido y eficiente buscar quiénes son tus contactos. Una pequeña mejora sería mover esto en una entidad separada padre es la persona por lo que no siempre va a cargar esos datos:

class Contacts { 
    @Parent Key<Person> owner; 
    @Id long id = 1; // there's only ever one of these per person, and it should have a predictable key for fetching 
    Set<Key<Person>> contacts; 
} 

Por supuesto, el conjunto en una sola entidad le da un límite de 50.000 de entrada. Podría ser un poco más pequeño que esto si primero tocas el límite de tamaño de la entidad de 1M. Si sus claves son ~ 20 caracteres, será más o menos lo mismo. Si esto es un problema, puede permitir varias entidades de contactos, en cuyo punto tiene algo parecido al patrón de entidad de índice de relación de la charla de E/S de Google 2009 de Brett Slatkin: http://www.youtube.com/watch?v=AgaL6NGpkB8

2) Puede almacenar una lista de contactos en la otra dirección

class Person { 
    @Id Long id; 
    @Index Set<Key<Peson>> contactOf; 
} 

Esto hace que sea un poco más caro para averiguar quiénes son sus contactos son - que necesita una consulta de solo claves, no una clave Ver por simple. Pero ya no estás realmente limitado por la tasa de escritura de la entidad. La gente probablemente no envíe más de un mensaje por segundo, y si envían 1000 mensajes en bloque, puede actualizar el contacto en una sola transacción.

Como el anterior, es probable que quieren mover este índice en una entidad separada:

class Contacts { 
    @Parent Key<Person> person; 
    @Id long id = 1; // there's only ever one of these per person, and it should have a predictable key for fetching 
    Set<Key<Person>> of; 
} 

3) También puede almacenar estos contactos en una entidad completamente separada

class Contact { 
    @Parent Key<Person> person; 
    @Id Long id; 
    @Index Key<Person> owner; 
} 

Esto realmente es sólo una forma menos eficiente de espacio de hacer la solución n. ° 2.

Lo importante es seguir actualizando esta estructura cuando se envía o recibe cada mensaje.

+0

Gracias por su amplia respuesta. Estoy haciendo algunas preguntas de seguimiento en google-appengine-group. – spierce7

+0

Tiene un límite de 5.000, no 50.000, probablemente un error tipográfico. – gswierczynski

Cuestiones relacionadas