ChilliCream / ChilliCream/graphql-platform
MongoDB projections with polymorphic types having an incorrect behavior
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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