-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CSHARP-4248: Allow collectionless $lookup with $documents. #1544
base: main
Are you sure you want to change the base?
Conversation
/// <notes>The Results property of <see cref="T:LookupResult{TSource,TDocument}"/> contains the matching foreign documents.</notes> | ||
public static IQueryable<LookupResult<TSource, TDocument>> Lookup<TSource, TDocument, TField>( | ||
this IQueryable<TSource> source, | ||
Expression<Func<TSource, IEnumerable<TDocument>>> documents, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
documents
could also be a constant but the server allows the documents to be computed.
/// <typeparam name="TField">The type of the fields being compared.</typeparam> | ||
/// <returns>An <see cref="T:IQueryable{LookupResult{TSource,TForeign}}"/> with the results of the Lookup.</returns> | ||
/// <notes>The Results property of <see cref="T:LookupResult{TSource,TForeign}"/> contains the matching foreign documents.</notes> | ||
public static IQueryable<LookupResult<TSource, TForeign>> Lookup<TSource, TForeign, TField>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These 6 new overloads correspond to the 6 variations of $lookup
supported by the server:
1: from with localField and foreignField
2. from with pipeline
3. from with localField and foreignField and pipeline (the "concise" syntax)
4. $documents
with localField and foreignField
5. $documents
with pipeline
6. $documents
with localField and foreignField and pipeline (the "concise" syntax)
AstProject.Exclude("_id")); | ||
var wrappedLocalSerializer = WrappedValueSerializer.Create("_local", localSerializer); | ||
|
||
IMongoCollection foreignCollection = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The technique here is to optionally construct the pieces that make up the lookup and then build the AST at the end.
Not all pieces are present in all overloads of Lookup
.
|
||
AstStage lookupStage = null; | ||
IBsonSerializer resultSerializer = null; | ||
if (method.Is(MongoQueryableMethod.LookupWithFromAndLocalFieldAndForeignField)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is where we start building the 6 variations of AST using the pieces that were created above.
context = context.WithSymbol(localSymbol); | ||
|
||
var provider = new MongoQueryProvider<TDocument>(documentSerializer, session: null, options: null); | ||
var queryable = new MongoQuery<TDocument, TDocument>(provider); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new way of creating an IQueryable
that is not tied to any particular collection.
Most of the time an IQueryable
is tied to a collection being queried (or possibly a database for some kinds of queries).
/// <typeparam name="TLocal">The type of the local documents.</typeparam> | ||
/// <typeparam name="TResult">The type of the result values.</typeparam> | ||
[BsonSerializer(typeof(LookupResultSerializer<,>))] | ||
public struct LookupResult<TLocal, TResult> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Class that is the result of a Lookup
.
/// <summary> | ||
/// The result values. | ||
/// </summary> | ||
public TResult[] Results { get; init; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The results are either the TForeign
documents or if a pipeline is provided then the TResult
of the pipeline.
_pipelineInputSerializer = NoPipelineInputSerializer.Instance; | ||
} | ||
|
||
internal MongoQueryProvider( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New constructor to support LINQ queries that aren't tied to any collection or database.
@@ -23,6 +23,13 @@ | |||
|
|||
namespace MongoDB.Driver | |||
{ | |||
internal interface IMongoCollection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally IMongoCollection<TDocument>
would derive from IMongoColletion
but that could be considered a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it is. Could you please add this to the TODO list for next major release? https://docs.google.com/document/d/1pGrELOhAvzXvavUDqIA-su0ic6wf2Mu6h20llrYj_VA
@@ -31,7 +31,7 @@ | |||
|
|||
namespace MongoDB.Driver | |||
{ | |||
internal sealed class MongoCollectionImpl<TDocument> : MongoCollectionBase<TDocument> | |||
internal sealed class MongoCollectionImpl<TDocument> : MongoCollectionBase<TDocument>, IMongoCollection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since IMongoCollection<TDocument>
does not derive from IMongoCollection
we have to list IMongoCollection
here as an interface we implement.
@@ -23,6 +23,13 @@ | |||
|
|||
namespace MongoDB.Driver | |||
{ | |||
internal interface IMongoCollection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it is. Could you please add this to the TODO list for next major release? https://docs.google.com/document/d/1pGrELOhAvzXvavUDqIA-su0ic6wf2Mu6h20llrYj_VA
Ensure.IsNotNull(localField, nameof(localField)); | ||
Ensure.IsNotNull(foreignField, nameof(foreignField)); | ||
|
||
return source.Provider.CreateQuery<LookupResult<TSource, TForeign>>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be source.GetMongoQueryProvider()
instead to validate the provider is IMongoQueryProvider
?
No description provided.