graphene-mongo icon indicating copy to clipboard operation
graphene-mongo copied to clipboard

What is intended way to implement Union?

Open sVerentsov opened this issue 6 years ago • 3 comments

Here is the schema that i am trying to implement:

type Text {
  id: ID
  content: String
}
type Image {
  id: ID
  image_url: String
  thumb_url: String
}
union Post = Text | Image
type User {
  id: ID
  posts: [Post]
}
type Query {
  users: [User]
}

and execute this query:

    {
        users {
            posts {
                ... on  Image {
                    image_url
                }
                ... on Text {
                    content
                }
            }
        }
    }

What I have tried:

  1. Mongoengine models: make PostModel as separate Document, inherit TextModel and ImageModel from it and reference PostModel from UserModel.
    Graphene objects: make types for Text, Image, User and Post as MongoengineObjectType.
    (full code here) This returns errors Unknown type "Image". and Unknown type "Text". In this case Post type has only fields Cls: String, id: ID.

  2. Mongoengine models: same.
    Graphene objects: inherit Post from graphene.Union and set Image and Text as types of that union. (full code here) This returns Cannot query field "posts" on type "User".. I suppose this happens because now graphene_mongo does not state that User.posts reference Post

So how should such schema be implemented?

sVerentsov avatar Dec 11 '19 17:12 sVerentsov

@sVerentsov : I will take a look, thanks.

abawchen avatar Dec 17 '19 03:12 abawchen

I managed to solve this by explicitly stating posts field in User:

class User(MongoengineObjectType):
    class Meta:
        model = UserModel
    posts = graphene.Field(graphene.List(lambda: Post))


class Post(graphene.Union):
    class Meta:
        types = (Image, Text)

Full working code here

It is quite suprising that graphene-mongo resolves posts as references of ImageModel and TextModel automatically.

sVerentsov avatar Dec 17 '19 13:12 sVerentsov

https://github.com/graphql-python/graphene-mongo/blob/33be6067a2c451428064d9e4338269dd50744715/graphene_mongo/tests/models.py#L61-L74

generic_reference = mongoengine.GenericReferenceField( 
         choices=[Article, Editor, ] 
     ) 

or you can use GenericReferenceField with choices to do it, but I have not verified ListField(mongoengine.GenericReferenceField()) works or not.

abawchen avatar Dec 19 '19 12:12 abawchen