0

J'ai modèles NDB:NDB Filtrage pour App Google Propriété Structured Engine

class Product(ndb.Model): 
    name = ndb.StringProperty() 
    description = ndb.StringProperty() 
    code = ndb.StringProperty() 

class Category(ndb.Model): 
    name = ndb.StringProperty() 

class Shop(ndb.Model): 
    name = ndb.StringProperty() 
    category = ndb.StructuredProperty(Category) 
    address = ndb.StringProperty() 

class ProductInShop(ndb.Model): 
    product = ndb.StructuredProperty(Product) 
    shop = ndb.StructuredProperty(Shop) 
    price = ndb.FloatProperty() 

Et dans une fonction que je dois trouver le produit dans le magasin (code produit et la clé de la boutique en demande). Si aucun produit dans la boutique (renvoyant None) alors j'ai besoin de le créer. S'il existe, mettez à jour la valeur du prix à partir de la demande. Maintenant, je fais une requête par gql.

product_in_shop = ndb.gql(
     'SELECT * FROM ProductInShop WHERE \ 
product.code = :1 AND shop = :2 LIMIT 1', 
     request.code, 
     ndb.Key(Shop, request.shop_key).get() 
    ).get() 

Et cela fonctionne très bien. Mais! Quelques fois product_in_shop = None quand il devrait y avoir une entité (j'ai été vérifié à la base de données). J'ai été tenté de faire une autre requête pour compter les entités et elle renvoie 0, mais il y avait plus d'une entité.

Quand je vois ce sac je peux simplement mettre à jour (python appcfg.py projet Nom -A la mise à jour nom_projet) et il fonctionne ...

Toutes les idées que je fais mal ou comment réparer?

+1

Je pense qu'il est lié à la cohérence éventuelle. https://cloud.google.com/datastore/docs/concepts/structuring_for_strong_consistency –

Répondre

1

Très probablement Eventual Consistency. Lorsque vous concevez votre système avec Cloud Datastore, vous devez prévoir que ces requêtes peuvent prendre du temps pour être mises à jour. Il est probable que le redéploiement de votre application dans ce cas prenne assez de temps pour que les informations soient mises à jour au moment de la nouvelle vérification. Pour garantir une bonne cohérence, vous devez organiser vos données dans les groupes d'entités. Une considération importante pour votre modèle de données est qu'au sein d'un EG vous pouvez interroger d'une manière fortement cohérente. Cependant, vous ne pouvez mettre à jour qu'un seul groupe d'entités à un rythme soutenu de 1 mise à jour par seconde (cette mise à jour pourrait toutefois être une mise à jour par lots). Essayez d'aligner ces groupes d'entités le long des limites naturelles afin de limiter le taux d'écriture d'un groupe d'entités donné en fonction de l'échelle de votre application. Par exemple, vous pouvez avoir un seul groupe d'entités par utilisateur ou, dans le cas de votre application, un seul groupe d'entités par Shop. Si vous mettez tous les Product s pour un seul Shop dans un groupe d'entités, vous pouvez toujours lister tous les Product dans un magasin d'une manière fortement cohérente. Vous ne seriez pas en mesure d'augmenter le nombre de personnes ajoutant des articles à un magasin (vous êtes limité à écrire des produits dans un magasin à un lot par seconde), mais cela serait probablement une contrainte acceptable pour le système.

considérant donc la mise en page suivante à la place:

class Product(ndb.Model): 
    name = ndb.StringProperty() 
    description = ndb.StringProperty() 
    code = ndb.StringProperty() 

class Category(ndb.Model): 
    name = ndb.StringProperty() 

class Shop(ndb.Model): 
    name = ndb.StringProperty() 
    category = ndb.StructuredProperty(Category) 
    address = ndb.StringProperty() 

class ProductInShop(ndb.Model): 
    product = ndb.StructuredProperty(Product) 
    price = ndb.FloatProperty() 

Lorsque vous créez un ProductInShop, vous aurez envie de mettre le parent à la clé de la Shop qu'elle est partie. Par exemple:

ProductInShop(parent=ndb.Key(Shop, request.shop_key), 
    product=Product(...), price=10.0).put() 

Ensuite, vous pouvez émettre votre requête pour un produit dans un magasin donné avec un code spécifique:

product_in_shop = ndb.gql(
     'SELECT * FROM ProductInShop WHERE \ 
product.code = :1 AND ANCESTOR IS :2 LIMIT 1', 
     request.code, 
     ndb.Key(Shop, request.shop_key) 
    ).get() 

Comme une note de côté, si votre code est unique à un seul produit, Envisagez de définir l'ID du ProductInShop comme étant le code.Ensuite, vous n'avez pas à émettre une requête pour cela:

ProductInShop(id=product.code, product=product, price=10.0).put() 

Ensuite, vous pouvez rechercher votre ProductInShop sans avoir à émettre une requête avec:

product_in_shop = ndb.Key(Shop, request.shop_key, ProductInShop, request.code).get()