Skip to content

Commit bbfaa36

Browse files
Fix nodes returning empty when only __typename is requested (#1170)
* Fix nodes returning empty when only __typename is requested When a query selects only `__typename` under `nodes` or `edges { node }`, `requested_fields` ends up empty (because `__typename` is a dynamic field and is stripped before populating `requested_fields`). This left `individual_docs_needed: false`, causing `size: 0` in the datastore query and returning no documents despite `total_edge_count > 0`. Fix by additionally setting `individual_docs_needed: true` whenever `nodes` or `edges.node` is selected at all — the client selecting that part of the query is itself the signal that individual documents are needed. Fixes #1055 Generated with Claude Code * Add unit tests for individual_docs_needed when only __typename is requested Covers the fix from the previous commit at the unit level, as requested in code review. Generated with Claude Code
1 parent fff64e7 commit bbfaa36

3 files changed

Lines changed: 69 additions & 1 deletion

File tree

elasticgraph-graphql/lib/elastic_graph/graphql/query_adapter/requested_fields.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def query_attributes_for(field:, lookahead:)
5555
.selection(@schema.element_names.highlights)
5656

5757
{
58-
individual_docs_needed: pagination_fields_need_individual_docs?(lookahead),
58+
individual_docs_needed: pagination_fields_need_individual_docs?(lookahead) || relay_connection_node_from(lookahead).selected?,
5959
requested_fields: requested_fields_under(relay_connection_node_from(lookahead), index_field_paths),
6060
request_all_highlights: requesting_all_highlights?(lookahead),
6161
requested_highlights: requested_fields_under(highlights, index_field_paths)

elasticgraph-graphql/spec/acceptance/search_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,42 @@ module ElasticGraph
913913
]
914914
end
915915

916+
it "returns nodes when querying only `__typename` with no other fields" do
917+
index_records(
918+
build(:address),
919+
build(:address),
920+
build(:electrical_part),
921+
build(:mechanical_part)
922+
)
923+
924+
# Concrete type: nodes { __typename }
925+
address_nodes = call_graphql_query(<<~QUERY).dig("data", "addresses", "nodes")
926+
query { addresses { nodes { __typename } } }
927+
QUERY
928+
expect(address_nodes).to contain_exactly(
929+
{"__typename" => "Address"},
930+
{"__typename" => "Address"}
931+
)
932+
933+
# Concrete type: edges { node { __typename } }
934+
address_edges = call_graphql_query(<<~QUERY).dig("data", "addresses", "edges")
935+
query { addresses { edges { node { __typename } } } }
936+
QUERY
937+
expect(address_edges).to contain_exactly(
938+
{"node" => {"__typename" => "Address"}},
939+
{"node" => {"__typename" => "Address"}}
940+
)
941+
942+
# Abstract type: nodes { __typename } (no type-specific fragments)
943+
part_nodes = call_graphql_query(<<~QUERY).dig("data", "parts", "nodes")
944+
query { parts { nodes { __typename } } }
945+
QUERY
946+
expect(part_nodes).to contain_exactly(
947+
{"__typename" => "ElectricalPart"},
948+
{"__typename" => "MechanicalPart"}
949+
)
950+
end
951+
916952
describe "`list` filtering behavior" do
917953
it "supports filtering on scalar lists, nested object lists, and embedded object lists", :expect_index_exclusions do
918954
index_records(

elasticgraph-graphql/spec/unit/elastic_graph/graphql/query_adapter/requested_fields_spec.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,38 @@ class QueryAdapter
669669
expect(query.individual_docs_needed).to be true
670670
end
671671

672+
it "sets `individual_docs_needed = true` when only `__typename` is requested under `nodes`" do
673+
query = datastore_query_for(:Query, :widgets, <<~QUERY)
674+
query {
675+
widgets {
676+
nodes {
677+
__typename
678+
}
679+
}
680+
}
681+
QUERY
682+
683+
expect(query.individual_docs_needed).to be true
684+
expect(query.requested_fields).to be_empty
685+
end
686+
687+
it "sets `individual_docs_needed = true` when only `__typename` is requested under `edges.node`" do
688+
query = datastore_query_for(:Query, :widgets, <<~QUERY)
689+
query {
690+
widgets {
691+
edges {
692+
node {
693+
__typename
694+
}
695+
}
696+
}
697+
}
698+
QUERY
699+
700+
expect(query.individual_docs_needed).to be true
701+
expect(query.requested_fields).to be_empty
702+
end
703+
672704
it "sets `individual_docs_needed = true` when an edge cursor is requested" do
673705
query = datastore_query_for(:Query, :widgets, <<~QUERY)
674706
query {

0 commit comments

Comments
 (0)