Skip to content
This repository has been archived by the owner on Jul 18, 2023. It is now read-only.

Selecting specific item properties of List type properties #38

Open
RavenLiquid opened this issue Dec 17, 2022 · 1 comment
Open

Selecting specific item properties of List type properties #38

RavenLiquid opened this issue Dec 17, 2022 · 1 comment

Comments

@RavenLiquid
Copy link

RavenLiquid commented Dec 17, 2022

I'm trying this out on the PokeApi GraphQL api, and I'm having a hard time figuring out how to either select a specific property of a list in a select query or do a subquery on the type.

pokemonContext.Pokemon_v2_pokemonspecies(
                    null,
                    null,
                    null,
                    null,
                    new pokemon_v2_pokemonspecies_bool_exp
                    {
                        Name = new string_comparison_exp { _ilike = name }
                    }
                )
                .Include(p => p.Pokemon_v2_pokemonevolutions.Select(evo => evo.Id) // Does nothing
                .Include(p => p.Pokemon_v2_pokemonevolutions(null, 1, 0, null, new pokemon_v2_pokemonevolution_bool_exp { Evolved_species_id = new int_comparison_exp { _eq = p.Id } }).Select(e => e.Id)) // Causes null error
                .Include(p => p.Evolution_chain_id)
                .Select(p =>
                    new
                    {
                        Id = p.Id,
                        Name = p.Name,
                        Evolutions = p.Pokemon_v2_pokemonevolutions,  // works but includes all properties
                        Evolutions = p.Pokemon_v2_pokemonevolutions.Select(evo => evo.Id),  // Does nothing
                        Evolutions = p.Pokemon_v2_pokemonevolutions(null, 0,0, null,  new pokemon_v2_pokemonevolution_bool_exp{ Evolved_species_id = new int_comparison_exp{ _eq = p.Id}}).AsQueryable().Select(e => e.Id), // Does nothing
                        EvolutionChainId = p.Evolution_chain_id,
                        BabyItemId = p.Pokemon_v2_evolutionchain.Baby_trigger_item_id // Correctly selects only the Baby_trigger_item_id 
                    });

Any type of filtering seems to omit the evolutions from the query.

I would have expected this to be generated

pokemon_v2_pokemonspecies(where: {name: {_like: "Name"}}) {
    id
    evolution_chain_id
    pokemon_v2_pokemonevolutions{
      id
    }
    name
  }

Some separate issues I encountered:
Scaffolding created all classes with an uppercase first character, this didn't work as it seems to expect lowercase names.
e.g. pokemon_v2_pokemonspecies_bool_exp instead of Pokemon_v2_pokemonspecies_bool_exp
kind of the opposite of #15

Debugging with the nuget package is impossible, the exceptions generated never have a message in the Errors property.

@RavenLiquid
Copy link
Author

Turns out this is not possible with the current way the library works. I've been massaging the existing workflow to do what I wanted in a quick and dirty way.
Maybe I'll clean it up in to a decent solution and make a pull request if there is interest.
If anyone wants to try it now here is the branch in my fork that generates and maps working queries.

It accepts this:

var pokemonContext = new QueryContext();
var pokemon = pokemonContext.Pokemon_v2_pokemonspecies(
		null,
		null,
		null,
		null,
		new pokemon_v2_pokemonspecies_bool_exp
		{
			Id = new int_comparison_exp{ _eq = id}
		}
	)
	.Select(p =>
		new
		{
			Id = p.Id,
			Name = p.Name,
			EvolvesFromId = p.Evolves_from_species_id,
			EvolutionChains = p.Pokemon_v2_evolutionchain.Pokemon_v2_pokemonspecies.Select(evo => 
			  new
			  {
				  evo.Id,
				  evo.Name,
				  evo.Evolves_from_species_id,
				  Trigger = new
				  {
					  Conditions = evo.Pokemon_v2_pokemonevolutions,
					  Name = evo.Pokemon_v2_pokemonevolutions.Select(e => e.Pokemon_v2_evolutiontrigger.Name)
				  }
			  }
			),
			EvolutionChainId = p.Evolution_chain_id,                      
			Variants = p.Pokemon_v2_pokemons.Select(pm => pm.Pokemon_v2_pokemonforms.Select(f => f.Form_name)),
			HasGenderDifferences = p.Has_gender_differences
		});

And will generate a query that selects only the requested properties. (Except the nice indentation, that has not been added)

query ($where: pokemon_v2_pokemonspecies_bool_exp) { result: pokemon_v2_pokemonspecies (where: $where) { 
    Id: id
    Name: name
    Evolves_from_species_id: evolves_from_species_id
    Evolution_chain_id: evolution_chain_id
    Has_gender_differences: has_gender_differences
    pokemon_v2_evolutionchain {
      pokemon_v2_pokemonspecies {
        Id: id
        Name: name
        Evolves_from_species_id: evolves_from_species_id
        Pokemon_v2_pokemonevolutions: pokemon_v2_pokemonevolutions {
          evolution_item_id
          evolution_trigger_id
          evolved_species_id
          gender_id
          held_item_id
          id
          known_move_id
          known_move_type_id
          location_id
          min_affection
          min_beauty
          min_happiness
          min_level
          needs_overworld_rain
          party_species_id
          party_type_id
          relative_physical_stats
          time_of_day
          trade_species_id
          turn_upside_down
          pokemon_v2_evolutiontrigger {
            Name: name
          }
        }
      }
    }
    pokemon_v2_pokemons {
      pokemon_v2_pokemonforms {
        Form_name: form_name
      }
    }
  }
}
Trigger = new
{
    Conditions = evo.Pokemon_v2_pokemonevolutions,
    Name = evo.Pokemon_v2_pokemonevolutions.Select(e => e.Pokemon_v2_evolutiontrigger.Name)
}

This part has a bit of an issue for which I created a workaround. The selected query for this would be valid and work, but it would return two 'Pokemon_v2_pokemonevolutions ' keys at the same level in the returned JSON, but with different values.
The deserializer would overwrite it with the last value, and it would then be mapped to both Conditions and Name.
Since the behavior of mapping it to both properties was acceptable for me, I added a merge for those types of situations. If a new clause has multiple members with the same name, it will attempt to merge them together.

It is pretty rough and probably will not work in all situations. Currently it supports only Select and new clauses. Member initialization is not tested or supported.
I'm currently trying to extend it with support for GraphQL queries as that is all I needed for my own project at the moment.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant