7

Estoy en el proceso de escribir mi primer servicio web RESTful encima de GAE y el tiempo de ejecución de Python 2.7; Empecé a usar la brillante nueva API de ndb de Guido.Tras referencias a tipos desconocidos en NDB

Sin embargo, no estoy seguro de cómo resolver un caso particular sin la característica de referencia implícita de la API de db original. Si el agente de usuario solicita un recurso en particular y los recursos de 1 grado Eliminado:?

host/API/tipo/Identificación profundidad = 2

Cuál es la mejor manera de descubrir una colección relacionada de entidades de la " uno "en una relación de uno a muchos, dado que el tipo de entidad relacionada se desconoce en el momento del desarrollo?

  • Soy incapaz de utilizar una consulta de sustitución como se describe en una previous SO inquiry debido a la última restricción. El hecho de que mi modelo sea definible en tiempo de ejecución (y, por lo tanto, no está codificado) me impide utilizar una consulta para filtrar las propiedades de las claves coincidentes.

  • El ancestro y otras consultas sin amables también se han eliminado debido a la limitación del almacén de datos que me impide filtrar en una propiedad sin el tipo especificado.

Hasta el momento, la única idea que he tenido (más allá de volver a la API db) es el uso de una transacción de todos los Grupos de escribir mi propia referencia en el "uno", ya sea mediante la actualización de un NDB. StringProperty (repeat = True) que contiene todos los tipos relacionados cuando se introduce una entidad de un nuevo tipo o simplemente manteniendo una lista de claves en el "uno" ndb.KeyProperty (repeat = True) cada vez que una entidad relacionada "muchos" es escrito en el almacén de datos.

Espero que alguien más experimentado que yo pueda sugerir un mejor enfoque.

Teniendo en cuenta la sugerencia de jmort253, voy a tratar de aumentar mi pregunta con un ejemplo concreto adaptado a partir de la documentación:

class Contact(ndb.Expando): 
    """ The One """ 

    # basic info 
    name = ndb.StringProperty() 
    birth_day = ndb.DateProperty() 

    # If I were using db, a collection called 'phone_numbers' would be implicitly 
    # created here. I could use this property to retrieve related phone numbers 
    # when this entity was queried. Since NDB lacks this feature, the service 
    # will neither have a reference to query nor the means to know the 
    # relationship exists in the first place since it cannot be hard-coded. The 
    # data model is extensible and user-defined at runtime; most relationships 
    # will be described only in the data, and must be discoverable by the server. 
    # In this case, when Contact is queried, I need a way to retrieve the 
    # collection of phone numbers. 

    # Company info. 
    company_title = ndb.StringProperty() 
    company_name = ndb.StringProperty() 
    company_description = ndb.StringProperty() 
    company_address = ndb.PostalAddressProperty() 

class PhoneNumber(ndb.Expando): 
    """ The Many """ 

    # no collection_name='phone_numbers' equivalent exists for the key property 
    contact = ndb.KeyProperty(kind='Contact') 
    number = ndb.PhoneNumberProperty() 
+0

Hola, ¿puedes mostrar un ejemplo para ayudar a entender el problema un poco mejor? Muchas personas son visuales, por lo que ver puede ayudar a aclarar su pregunta. ¡Buena suerte!:) – jmort253

+0

Si no sabes qué tipo de entidad estás buscando, ¿qué vas a hacer con ellos cuando los obtengas? –

+0

La capa de servicio simplemente serializará las entidades relacionadas que descubrió en la representación JSON de la entidad solicitada explícitamente. Depende de la aplicación del cliente determinar cómo se usan; al servidor no le importa – yo22arian

Respuesta

8

¡Pregunta interesante! Así que, básicamente, desea consultar la clase de contacto y averiguar si hay alguna otra clase de modelo que tenga una propiedad KeyProperty que haga referencia a ella; en este ejemplo PhoneNumber (pero podría haber muchos).

Creo que la solución es pedirles a los usuarios que agreguen explícitamente este enlace cuando se cree la clase PhoneNumber.

Puede hacer que esto sea fácil para sus usuarios al proporcionarles una subclase de KeyProperty que se ocupa de esto; p.ej.

class LinkedKeyProperty(ndb.KeyProperty): 
    def _fix_up(self, cls, code_name): 
     super(LinkedKeyProperty, self)._fix_up(cls, code_name) 
     modelclass = ndb.Model._kind_map[self._kind] 
     collection_name = '%s_ref_%s_to_%s' % (cls.__name__, 
               code_name, 
               modelclass.__name__) 
     setattr(modelclass, collection_name, (cls, self)) 

Exactamente cómo elige el nombre de la colección y el valor que debe almacenar; depende de usted; simplemente coloque algo allí que le facilite seguir el enlace de regreso. El ejemplo crearía un nuevo atributo en Contacto:

Contact.PhoneNumber_ref_contact_to_Contact == (PhoneNumber, PhoneNumber.contact) 

[editado para que el código funcione y para agregar un ejemplo. :-)]

+0

Muchas gracias por la publicación, y aún más por la elaboración no solicitada. B) Tu sinopsis del problema es puntual. Esto también parece ser el enfoque correcto. Poco a poco estoy empezando a adquirir una comprensión de la mecánica que hay detrás mientras exploro la fuente del paquete; sin embargo, self._kind, que corresponde al kwarg pasado al constructor LinkedKeyProperty (kind = 'Contact'), no existe en el mapa tipo por alguna razón, al menos no en mi implementación. En el caso del ejemplo, supongo que esto debería recuperar una referencia al modelo de contacto. – yo22arian

+0

'ndb.Model._kind_map [self._kind] == * crash *' – yo22arian

+0

Si escribe LinkedKeyProperty exactamente como lo demostré, debería funcionar. ¿Quizás no lo derivaste de ndb.KeyProperty? ¿O no hiciste la llamada súper() primero? Si no puede hacer que funcione, muestre el código completo que intentó y el rastreo completo. –

2

sonido como un buen caso de uso para ndb.StructuredProperty.

+1

¡Gracias por la sugerencia! Sin embargo, ndb.StructuredProperty tiene su propia limitación de descalificación en mi caso: "no se puede recuperar independientemente de la entidad de contacto a la que [pertenece]". – yo22arian

Cuestiones relacionadas