2012-12-18 21 views
14

Soruma ndb'de bire çok ilişki modelleme ile ilgili. Bunun (en azından) iki farklı yolla yapılabileceğini anlıyorum: tekrarlanan bir mülkle veya bir 'yabancı anahtarla'. Aşağıda küçük bir örnek oluşturdum. Temel olarak, keyfi sayıda Etikete sahip bir Madde var. Bir Etiketin kaldırılabildiğini ancak eklendikten sonra değiştirilemeyeceğini varsayalım. Ayrıca, işlem güvenliği konusunda endişelenmediğimizi varsayalım.ndb bire çok modelleme: yinelenen KeyProperty vs yabancı anahtarın faydaları

Sorum şu: Bu ilişkileri modellemenin tercih edilen yolu nedir?

Benim hususlar:

  • Yaklaşım (A) sadece gerektirir (B) yaklaşım ise bir makalesinde (Etiketi için maddesinde için ve bir) eklenir her etiket için iki yazma gerektirir bir yazı (sadece Tag). bazı şeyler yaklaşımı (B) bir sorgu gerekli (ve ek olarak bazı özel önbelleğe) olduğu

durumunda oysa bir maddede için tüm Etiketler var mıdır getirirken

  • Yaklaşım (A) NDB en önbelleğe alma mekanizmasını güçlendirir Burada eksik olduğum, dikkate alınması gereken başka bir şey var mı?

    Yardımlarınız için çok teşekkürler.

    Örnek (A):

    class Article(ndb.Model): 
        title = ndb.StringProperty() 
        # some more properties 
        tags = ndb.KeyProperty(kind="Tag", repeated=True) 
    
        def create_tag(self): 
         # requires two writes 
         tag = Tag(name="my_tag") 
         tag.put() 
         self.tags.append(tag) 
         self.put() 
    
        def get_tags(self): 
         return ndb.get_multi(self.tags) 
    
    class Tag(ndb.Model): 
        name = ndb.StringProperty() 
        user = ndb.KeyProperty(Kind="User") # User that created the tag 
        # some more properties 
    

    Örnek (B):

    class Article(ndb.Model): 
        title = ndb.StringProperty() 
        # some more properties 
    
        def create_tag(self): 
         # requires one write 
         tag = Tag(name="my_tag", article=self.key) 
         tag.put() 
    
        def get_tags(self): 
         # obviously we could cache this query in memcache 
         return Tag.gql("WHERE article :1", self.key) 
    
    class Tag(ndb.Model): 
        name = ndb.StringProperty() 
        article = ndb.KeyProperty(kind="Article") 
        user = ndb.KeyProperty(Kind="User") # User that created the tag 
        # some more properties 
    
  • +2

    Performansı belirli bir sorununun belirli bir cevabı olabileceği gibi, özellikle de gerçek kullanımınızla daha fazla ilişkili olduğu ve bu nedenle de yukarıdaki uygulama seçeneklerinden hangilerinin gerçek hayatta daha verimli olduğunu anlatabildiği gibi, uygulamaların uygulama sürümlerini kontrol etmeyi düşünün. Aynı etikette olsa bile, https://developers.google.com/appengine/docs/python/tools/appstats –

    +2

    her makale için yeni etiketler oluşturursunuz? 'A' seçeneği için giderdim çünkü her makale için aynı 'Tag'ı kullanabileceksiniz ve 'Articles' etiketine göre sorgulayabileceksiniz. – aschmid00

    +0

    @PaulC teşekkürler. Aslında, appstats ile kontrol ettim ve benim durumumda B seçeneği daha verimli (1 yaz vs 2). Bununla birlikte, optimizasyon sadece küçük olduğundan, bire-bir ilişkiyi çözmek için belgelenmiş şekilde (yani seçenek A) vazgeçmeye değip değmeyeceğinden emin değilim. –

    cevap

    6

    Eğer Structured Propertieshttps://developers.google.com/appengine/docs/python/ndb/properties#structured kullanma hakkında aşağıdaki baktınız mı. Orada Contact ve Addresse ile ilgili kısa tartışma sorununuzu basitleştirebilir. Ayrıca https://developers.google.com/appengine/docs/python/ndb/queries#filtering_structured_properties'a bakın. Tartışmalar çok kısa.

    Ayrıca, birleştirme işlemlerine izin verilmediğinden emin olmak için A seçeneği daha iyi görünüyor.

    +0

    Cevabınız için teşekkürler, yapısal özellikler işi yapabilir ama benim özel durumumda en iyi çözüm olacağını düşünmüyorum. "Katılmaya izin verilmediğine dair ileriye bakarak" ile ne demek istiyorsun? Bu bir GAE politikası mı? –

    +1

    Evet, bu, veri mağazasının bir kısıtlamasıdır. https://developers.google.com/appengine/docs/python/datastore/queries adresini ziyaret edin. "özellikle, birleştirmeler ve toplu sorgular Datastore sorgu altyapısında desteklenmiyor." Veri mağazasında muhtemelen aşina olmanız gereken başka kısıtlamalar var: https://developers.google.com/appengine/docs/python/datastore/queries#Restrictions_on_Queries – kasavbere

    1

    Daha önce de belirtildiği gibi, Datastore'da birleşme yoktur, bu nedenle tüm "Yabancı Anahtar" kavramı geçerli değildir. Ne yapılabilir, Doğru Etiket için veri mağazanızı sorgulamak için Sorgu sınıfını kullanmaktır. Örneğin

    , daha sonra, merkezi ✘ kullanıyorsanız: istek sırasında

    class Tag(ndb.model): 
        user = ndb.UserProperty() 
    

    Ve yapın:

    query.filter(Tag.user == endpoints.get_current_user()) 
    
    0

    Yaklaşım (A) çoğu durumda tercih edilmelidir. Bir etiket eklemek için gereken iki yazma olsa da, bu muhtemelen etiketleri okumaktan çok daha az sıklıkta görülür. Çok sayıda etiketiniz olmadığı sürece, hepsi tekrarlanan Key özelliğine uymalıdır.

    Belirtildiği gibi, etiketleri anahtarlarına göre almak bir sorgulamadan çok daha hızlıdır.Yalnızca etiketinin adını ve kullanıcıyı gerekirse Ayrıca, üst anahtarı olarak User ve etiketin kimliğiyle Name ile etiket oluşturabilirsiniz:

    User -> Name -> Tag 
    

    bu etiketi oluşturmak için, istersek:

    Eğer etiketlerini almak zaman
    tag = Tag(id=name, parent=user, ...) 
    article.tags.push(tag) 
    ndb.put_multi([tag, article]) 
    

    Sonra

    for tag in article.tags: 
        user = tag.parent() 
        name = tag.id() 
    

    Sonra Article.tags saklanan her anahtar Kullanıcı anahtarı veiçerecektiradı! Bu, bu değerleri almak için Tag'da okumayı engeller.

    İlgili konular