question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Document subclasses are cast to parent class in query results

See original GitHub issue

I know I’m missing something. Given a model with multiple document types in a collection:

class AModel(Document):
    meta = {'allow_inheritance': True}
    a_field = StringField()

class ASubModel(AModel):
    a_sub_field = StringField()

I can construct a schema and query:

class A(MongoengineObjectType):                                           
    class Meta:                                                                
        model = AModel                                                    
        interfaces = (Node,)                                                   

class ASub(A):                                                      
    class Meta:                                                                
        model = ASubModel                                                
        interfaces = (Node,)

class Query(graphene.ObjectType):                                              
    node = Node.Field()                                                        
    all_a = MongoengineConnectionField(A)                           

If I run the allA query, I get back all the documents as expected, but I can’t access ASub’s fields because the returned type is A, not ASub, even though the class is identified as A.ASub. E.g.,:

{
  "data": {
    "allA": {
      "edges": [
        {
          "node": {
            "id": "VGFyZ2V0OjVjZTVmOTMwMjRmN2NhMGJmMjZlNzZmMQ==",
            "Cls": "A.ASub",
            "__typename": "A"
          }
        }
     ]
  }
}

Attempting to resolve ASub.a_sub_field results in an error. Inline fragment doesn’t work either:

{
  "errors": [
    {
      "message": "Fragment cannot be spread here as objects of type A can never be of type ASub",
      "locations": [
        {
          "line": 8,
          "column": 9
        }
      ]
    }
  ]
}

I’m clearly doing something wrong, but I don’t know what.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5

github_iconTop GitHub Comments

2reactions
Cerebuscommented, Jun 17, 2019

Yes, but…if I add a new Document subclass,

class ASub_new(A):
    pass

Then I have a different problem.

I could use a union, but even that makes me unhappy since I still have to modify the Query class every time I extend the data model. Further, it seems like it takes me away from Relay’s interface, which I’d rather not do.

1reaction
Cerebuscommented, May 25, 2019

Using the examples above, mongoengine returns the subclass when fetching on the parent class, which is IMHO correct behavior:

>>> AModel.objects.all()
[<ASubModel: ASubModel object>]

However, MongoengineConnectionField descends from graphene.Field, which adopts the named class as the only possible type. As a result, when the query is run returned results are being cast to MongoengineConnectionField._type, which is the parent class in this example. The casting works because of inheritance, but it’s unexpected behavior when you’re using a mongo backend.

I don’t think the other graphene backends won’t have this issue.

IMHO this is a bug. Document subclassing is a key mongo feature, so graphene_mongo should support it. I think the right way is to override graphene’s behavior here and set __typename to the returned object’s class, with an assertion that the returned object is a subclass of MongoengineConnectionField._type.

I think this would allow inline fragments to access fields on each subclass in a way compatible with mongo.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can Hibernate Criteria query for subclasses using Restrictions ...
I would like to use the following Criteria query but this results in a ClassCastException since Class cannot be cast to String ....
Read more >
Java static code analysis: Classes should not access their ...
Classes should not access their own subclasses during initialization ... When a parent class references a member of a subclass during its own...
Read more >
FindBugs Bug Descriptions - SourceForge
This class defines a compareTo(...) method but inherits its equals() method from java.lang.Object . Generally, the value of compareTo should ...
Read more >
Inheritance — What your mother never told you, C++ FAQ
Should a derived class redefine (“override”) a member function that is non- virtual in a base class? What's the meaning of, Warning: Derived::f(char)...
Read more >
Inheritance in PowerShell Classes - SAPIEN Information Center
So, the AnyGlass class inherits from its parent and grandparent classes — its entire ancestry — just like people do. Add Members to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found