ChilliCream / ChilliCream/graphql-platform

MongoDB projections with polymorphic types having an incorrect behavior

Open
#8,885 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

🌶️ hot chocolate Area: MongoDB
Dominant language
C#
Stars
5.8k
Forks
810
Avg merge
15h 39m
Merged PRs (30d)
98

Description

Product

Hot Chocolate

Version

15.1.0

Link to minimal reproduction

https://fileroy.com/qw1zen8xGXyn/file

Steps to reproduce

Issue the following polymorphic query on Animal:

query {
  faunas {
    name
    animals {
      name
      age
      species
      ... on Dog {
        breed
        isGoodBoy
      }
      ... on Cat {
        isIndoor
        livesUsed
      }
      ... on Bird {
        canFly
        wingspanCm
      }
    }
  }
}

This should be able to get all animals and deserialize them using their proper discriminators (configured in MongoDB maps).

What is expected?

Something like:

{
  "data": {
    "faunas": [
      {
        "name": "Savannah",
        "animals": [
          {
            "__typename": "Dog",
            "name": "Rex",
            "age": 4,
            "species": "Canis lupus familiaris",
            "breed": "Labrador",
            "isGoodBoy": true
          },
          {
            "__typename": "Cat",
            "name": "Misty",
            "age": 3,
            "species": "Felis catus",
            "isIndoor": false,
            "livesUsed": 2
          },
          {
            "__typename": "Bird",
            "name": "Skye",
            "age": 1,
            "species": "Psittaciformes",
            "canFly": true,
            "wingspanCm": 28
          }
        ]
      }
    ]
  }
}
What is actually happening?

I am getting errors:

{
  "errors": [
    {
      "message": "Cannot return null for non-nullable field.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "faunas"
      ],
      "extensions": {
        "code": "HC0018"
      }
    },
    {
      "message": "Could not resolve the actual object type from `Animal` for the abstract type `animals`.",
      "locations": [
        {
          "line": 4,
          "column": 5
        }
      ],
      "path": [
        "faunas",
        0,
        "animals",
        0
      ]
    }
  ],
  "data": null
}

It seems Hotchocolate is failing to project the correct field used as a discriminator (i.e., _t or any other custom element name for the discriminator by using the ObjectDiscriminatorConvention).

This is the input sent to MongoDB after applying the projection:

{
  "find" : "Faunas",
  "filter" : { },
  "projection" : {
    "an.WingspanCm" : 1,
    "an.CanFly" : 1,
    "an.LivesUsed" : 1,
    "an.IsIndoor" : 1,
    "an.IsGoodBoy" : 1,
    "an.Breed" : 1,
    "an.spec" : 1,
    "an.age" : 1,
    "an.n" : 1,
    "n" : 1
  },
  // (...)
}

Additionally, if there are custom MongoDB element names specified, those are not respected in the projection for the subclasses of Animal. I have set custom BsonElement names for all properties, and apparently for specific subclass elements, the proper mapping cannot be found and therefore the code property name is used instead.

Example:

public class Cat : Animal
{
    [BsonElement("i")] public bool IsIndoor { get; set; }

    [BsonElement("lu")] public int LivesUsed { get; set; }
}

In the projection above, we can see that instead of the correct lu name for the LivesUsed field, the projection sends out an.LivesUsed. While the first part an is correct (because an is the correct BsonElement name in the Fauna object for Animals), the LivesUsed field is not considering the custom element name mapping.

Relevant log output

Additional context

Please let me know if you need any other example. I'm attaching the working solution to the issue.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the attached minimal reproduction and inspect the MongoDB projection generated for the polymorphic Animal query. Trace how ObjectDiscriminatorConvention and custom BsonElement mappings are handled for subclass fields. Done means the projection includes the discriminator and mapped subclass element names, and the query returns the expected Dog, Cat, and Bird objects.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, mongodb
Domain
backend-api-design, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.