-
Type:
Improvement
-
Resolution: Unresolved
-
Priority:
Minor - P4
-
None
-
Affects Version/s: None
-
Component/s: LINQ
-
None
-
None
-
Dotnet Drivers
-
None
-
None
-
None
-
None
-
None
-
None
Currently, SelectMany with a collection selector and result selector is only supported as a top-level query operator (translating to $project + $unwind). It is not supported in nested array expressions (e.g., inside a Select projection).
This SelectMany overload takes two lambdas: a collection selector that picks which nested collection to flatten, and a result selector that combines the outer element with each inner element. This is useful when you need to flatten a nested array while retaining data from the parent element — similar to a SQL JOIN between a parent and its children.
For example, this does not work today:
// Given a document with: { Orders: [{ Store: "A", Items: [1, 2] }, { Store: "B", Items: [3] }] } // Flatten Items while keeping the Store from each Order: collection.AsQueryable().Select(doc => doc.Orders.SelectMany(order => order.Items, (order, item) => new { order.Store, item })) // Expected: [{ Store: "A", item: 1 }, { Store: "A", item: 2 }, { Store: "B", item: 3 }]
Supporting this in the expression translator would translate to $map + $reduce + $concatArrays, similar to how the simpler SelectMany(selector) overload already works there.
Once the base overload is supported in nested expressions, the index variant comes along naturally using arrayIndexAs on $map (the same mechanism added in CSHARP-5847):
collection.AsQueryable()
.Select(doc => doc.Orders.SelectMany((order, i) => order.Items, (order, item) => new { order.Store, item, Index = i }))
Note: the index variant at the pipeline level (top-level query) is not feasible in MQL — the index would represent a document's position in the pipeline stream, which has no clean MQL equivalent.
The reflection definitions for both overloads already exist in the codebase (EnumerableMethod and QueryableMethod) but are not wired up to the expression translator.