2012-08-03 2 views
4

depuis quatre jours j'essaie de comprendre comment suivre une référence d'une classe à une autre, en commençant par la classe qui est référencée. Dans SQL-Django il y a un related_name pour y parvenir ...MongoDB - MongoEngine - Comment suivre une référence de "l'autre côté"?

Par exemple, j'ai cette classe:

class MyClass(Document): 
    ... 
    other_classes = ListField(ReferenceField(Other_Class)) 

et celui-ci:

class Other_Class(Document): 
    ... 

Maintenant, je veux aller de Other_Class à MyClass ... Des idées?

Merci,

Ron

Répondre

3

Voici un test montrant comment il recherche:

import unittest 
from mongoengine import * 


class StackOverFlowTest(unittest.TestCase): 

    def setUp(self): 
     conn = connect(db='mongoenginetest') 

    def test_one_two_many(self): 

     class MyClass(Document): 
      other_classes = ListField(ReferenceField("OtherClass")) 

     class OtherClass(Document): 
      text = StringField() 

     MyClass.drop_collection() 
     OtherClass.drop_collection() 

     o1 = OtherClass(text='one').save() 
     o2 = OtherClass(text='two').save() 
     m = MyClass(other_classes=[o1, o2]).save() 

     # Lookup MyClass that has o1 in its other_classes 
     self.assertEqual(m, MyClass.objects.get(other_classes=o1)) 

     # Lookup MyClass where either o1 or o2 matches 
     self.assertEqual(m, MyClass.objects.get(other_classes__in=[o1, o2])) 

La principale question est de savoir si vous devez stocker une liste de références dans le MyClass? Il peut être plus efficace de stocker la relation uniquement sur OtherClass ..

0

Tout en pensant à mon problème, je suis venu avec une solution.

Je viens d'ajouter l'ID de ma classe référencée à mon modèle.

Voici un exemple:

class MyClass(Document): 
    ... 
    other_classes = ListField(ReferenceField(Other_Class)) 

class Other_Class(Document): 
    myclass = ReferenceField(MyClass) 

Je ne suis pas sûr si cela est le Mongo-façon de le faire, mais je suis sûr que cela fonctionne :)

En option, vous pouvez omettre le other_classes attribut MyClass pour éviter la redondance, mais alors vous avez besoin d'une requête comme celui-ci pour obtenir les objets « enfant »:

+0

Ceci est possible mais il n'est pas nécessaire de gérer deux références pour la relation. – Ross

0

Essayez cette requête:

oc = Other_Class() 
MyClass.objects.find(other_classes__all = [oc.id]) 
+0

bonne idée ... mais cette requête a-t-elle une bonne performance par rapport à ma solution "redondante"? – Ron

+2

@Ron Votre solution a des performances nettement meilleures. Cependant, il peut être un peu difficile de garder les références croisées synchronisées. En fait, la meilleure chose à faire est d'utiliser 'ReferenceField' dans' Other_Class' et de supprimer le champ 'other_classes' de' MyClass'. Vous n'en avez pas besoin, car vous devez de toute façon lancer une requête pour 'other_classes'. – freakish

+0

Merci pour la réponse. Mais si je supprime le 'ListField' dans 'MyClass', comment puis-je obtenir les 'Other_Class' à partir de 'MyClass'? Par exemple si j'ai un sujet et plusieurs messages. De temps en temps je devrais commencer à un poste et obtenir le fil parent. Mais dans la plupart des cas, je commence juste avec le fil et j'ai besoin de tous mes messages. Alors, comment puis-je supprimer le ListField dans Threads? (Oui, un message serait un document incorporé dans un thread, mais c'est juste un exemple;)) – Ron

Questions connexes