Skip to content

Commit 6233740

Browse files
committed
Address pr comments
1 parent 7c8e1de commit 6233740

7 files changed

+136
-210
lines changed

src/MongoDB.Driver/GeoNearOptions.cs

+18-11
Original file line numberDiff line numberDiff line change
@@ -13,49 +13,56 @@
1313
* limitations under the License.
1414
*/
1515

16+
using MongoDB.Bson.Serialization;
17+
1618
namespace MongoDB.Driver
1719
{
1820
/// <summary>
1921
/// Represents options for the $geoNear stage.
2022
/// </summary>
21-
public record GeoNearOptions<TDocument>
23+
public class GeoNearOptions<TInputDocument, TOutputDocument>
2224
{
2325
/// <summary>
2426
/// Gets or sets the output field that contains the calculated distance. Required if querying a time-series collection.
2527
/// Optional for non-time series collections in MongoDB 8.1+
2628
/// </summary>
27-
public string DistanceField { get; set; }
28-
29+
public FieldDefinition<TOutputDocument> DistanceField { get; set; }
30+
2931
/// <summary>
3032
/// Gets or sets the factor to multiply all distances returned by the query.
3133
/// </summary>
3234
public double? DistanceMultiplier { get; set; }
33-
35+
3436
/// <summary>
3537
/// Gets or sets the output field that identifies the location used to calculate the distance.
3638
/// </summary>
37-
public string IncludeLocs { get; set; }
38-
39+
public FieldDefinition<TOutputDocument> IncludeLocs { get; set; }
40+
3941
/// <summary>
4042
/// Gets or sets the geospatial indexed field used when calculating the distance.
4143
/// </summary>
4244
public string Key { get; set; }
43-
45+
4446
/// <summary>
4547
/// Gets or sets the max distance from the center point that the documents can be.
4648
/// </summary>
4749
public double? MaxDistance { get; set; }
48-
50+
4951
/// <summary>
5052
/// Gets or sets the min distance from the center point that the documents can be.
5153
/// </summary>
5254
public double? MinDistance { get; set; }
53-
55+
56+
/// <summary>
57+
/// Gets or sets the output serializer.
58+
/// </summary>
59+
public IBsonSerializer<TOutputDocument> OutputSerializer { get; set; }
60+
5461
/// <summary>
5562
/// Gets or sets the query that limits the results to the documents that match the query.
5663
/// </summary>
57-
public FilterDefinition<TDocument> Query { get; set; }
58-
64+
public FilterDefinition<TInputDocument> Query { get; set; }
65+
5966
/// <summary>
6067
/// Gets or sets the spherical option which determines how to calculate the distance between two points.
6168
/// </summary>

src/MongoDB.Driver/IAggregateFluentExtensions.cs

+6-7
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,10 @@ public static IAggregateFluent<TNewResult> Facet<TResult, TNewResult>(
263263
/// <param name="near">The point for which to find the closest documents.</param>
264264
/// <param name="options">The options.</param>
265265
/// <returns>The fluent aggregate interface.</returns>
266-
public static IAggregateFluent<TNewResult> GeoNear<TCoordinates, TResult, TNewResult>(
266+
public static IAggregateFluent<TNewResult> GeoNear<TResult, TCoordinates, TNewResult>(
267267
this IAggregateFluent<TResult> aggregate,
268268
GeoJsonPoint<TCoordinates> near,
269-
GeoNearOptions<TResult> options = null)
269+
GeoNearOptions<TResult, TNewResult> options = null)
270270
where TCoordinates : GeoJsonCoordinates
271271
{
272272
Ensure.IsNotNull(aggregate, nameof(aggregate));
@@ -278,18 +278,17 @@ public static IAggregateFluent<TNewResult> GeoNear<TCoordinates, TResult, TNewRe
278278
/// </summary>
279279
/// <typeparam name="TResult">The type of the result.</typeparam>
280280
/// <typeparam name="TNewResult">The type of the new result.</typeparam>
281-
/// <typeparam name="TCoordinates">The type of the coordinates for the point.</typeparam>
282281
/// <param name="aggregate">The aggregate.</param>
283282
/// <param name="near">The point for which to find the closest documents.</param>
284283
/// <param name="options">The options.</param>
285284
/// <returns>The fluent aggregate interface.</returns>
286-
public static IAggregateFluent<TNewResult> GeoNear<TCoordinates, TResult, TNewResult>(
285+
public static IAggregateFluent<TNewResult> GeoNear<TResult, TNewResult>(
287286
this IAggregateFluent<TResult> aggregate,
288-
TCoordinates[] near,
289-
GeoNearOptions<TResult> options = null)
287+
double[] near,
288+
GeoNearOptions<TResult, TNewResult> options = null)
290289
{
291290
Ensure.IsNotNull(aggregate, nameof(aggregate));
292-
return aggregate.AppendStage(PipelineStageDefinitionBuilder.GeoNear<TResult, TCoordinates, TNewResult>(near, options));
291+
return aggregate.AppendStage(PipelineStageDefinitionBuilder.GeoNear<TResult, TNewResult>(near, options));
293292
}
294293

295294
/// <summary>

src/MongoDB.Driver/PipelineDefinitionBuilder.cs

+7-27
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ public static PipelineDefinition<TInput, TInput> For<TInput>(IBsonSerializer<TIn
484484
{
485485
return new EmptyPipelineDefinition<TInput>(inputSerializer);
486486
}
487-
487+
488488
/// <summary>
489489
/// Appends a $geoNear stage to the pipeline.
490490
/// </summary>
@@ -499,33 +499,13 @@ public static PipelineDefinition<TInput, TInput> For<TInput>(IBsonSerializer<TIn
499499
public static PipelineDefinition<TInput, TOutput> GeoNear<TInput, TIntermediate, TCoordinates, TOutput>(
500500
this PipelineDefinition<TInput, TIntermediate> pipeline,
501501
GeoJsonPoint<TCoordinates> near,
502-
GeoNearOptions<TIntermediate> options = null)
502+
GeoNearOptions<TIntermediate, TOutput> options = null)
503503
where TCoordinates : GeoJsonCoordinates
504504
{
505505
Ensure.IsNotNull(pipeline, nameof(pipeline));
506-
return pipeline.AppendStage(PipelineStageDefinitionBuilder.GeoNear<TIntermediate, TCoordinates, TOutput>(near, options));
507-
}
508-
509-
/// <summary>
510-
/// Appends a $geoNear stage to the pipeline.
511-
/// </summary>
512-
/// <typeparam name="TInput">The type of the input documents.</typeparam>
513-
/// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
514-
/// <typeparam name="TOutput">The type of the output documents.</typeparam>
515-
/// <typeparam name="TCoordinates">The type of the coordinates for the point.</typeparam>
516-
/// <param name="pipeline">The pipeline.</param>
517-
/// <param name="near">The point for which to find the closest documents.</param>
518-
/// <param name="options">The options.</param>
519-
/// <returns>A new pipeline with an additional stage.</returns>
520-
public static PipelineDefinition<TInput, TOutput> GeoNear<TInput, TIntermediate, TCoordinates, TOutput>(
521-
this PipelineDefinition<TInput, TIntermediate> pipeline,
522-
TCoordinates[] near,
523-
GeoNearOptions<TIntermediate> options = null)
524-
{
525-
Ensure.IsNotNull(pipeline, nameof(pipeline));
526-
return pipeline.AppendStage(PipelineStageDefinitionBuilder.GeoNear<TIntermediate, TCoordinates, TOutput>(near, options));
506+
return pipeline.AppendStage(PipelineStageDefinitionBuilder.GeoNear(near, options));
527507
}
528-
508+
529509
/// <summary>
530510
/// Appends a $geoNear stage to the pipeline.
531511
/// </summary>
@@ -538,11 +518,11 @@ public static PipelineDefinition<TInput, TOutput> GeoNear<TInput, TIntermediate,
538518
/// <returns>A new pipeline with an additional stage.</returns>
539519
public static PipelineDefinition<TInput, TOutput> GeoNear<TInput, TIntermediate, TOutput>(
540520
this PipelineDefinition<TInput, TIntermediate> pipeline,
541-
BsonDocument near,
542-
GeoNearOptions<TIntermediate> options = null)
521+
double[] near,
522+
GeoNearOptions<TIntermediate, TOutput> options = null)
543523
{
544524
Ensure.IsNotNull(pipeline, nameof(pipeline));
545-
return pipeline.AppendStage(PipelineStageDefinitionBuilder.GeoNear<TIntermediate, BsonDocument, TOutput>(near, options));
525+
return pipeline.AppendStage(PipelineStageDefinitionBuilder.GeoNear(near, options));
546526
}
547527

548528
/// <summary>

src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs

+20-36
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ public static PipelineStageDefinition<TInput, TOutput> Facet<TInput, TOutput>(
604604
{
605605
return Facet<TInput, TOutput>((IEnumerable<AggregateFacet<TInput>>)facets);
606606
}
607-
607+
608608
/// <summary>
609609
/// Creates a $geoNear stage.
610610
/// </summary>
@@ -616,7 +616,8 @@ public static PipelineStageDefinition<TInput, TOutput> Facet<TInput, TOutput>(
616616
/// <returns>The stage.</returns>
617617
internal static PipelineStageDefinition<TInput, TOutput> GeoNear<TInput, TPoint, TOutput>(
618618
TPoint near,
619-
GeoNearOptions<TInput> options = null)
619+
GeoNearOptions<TInput, TOutput> options = null)
620+
// where TPoint is either a GeoJsonPoint or a legacy coordinate array
620621
{
621622
const string operatorName = "$geoNear";
622623
var stage = new DelegatedPipelineStageDefinition<TInput, TOutput>(
@@ -625,26 +626,27 @@ internal static PipelineStageDefinition<TInput, TOutput> GeoNear<TInput, TPoint,
625626
{
626627
ClientSideProjectionHelper.ThrowIfClientSideProjection(args.DocumentSerializer, operatorName);
627628
var pointSerializer = args.SerializerRegistry.GetSerializer<TPoint>();
629+
var outputSerializer = options?.OutputSerializer ?? args.GetSerializer<TOutput>();
630+
var outputRenderArgs = args.WithNewDocumentType(outputSerializer);
628631
var geoNearOptions = new BsonDocument
629632
{
630633
{ "near", pointSerializer.ToBsonValue(near)},
631-
{ "distanceField", options?.DistanceField, options?.DistanceField != null },
632-
{ "maxDistance", () => options?.MaxDistance.Value, options?.MaxDistance != null },
633-
{ "minDistance", () => options?.MinDistance.Value, options?.MinDistance != null },
634-
{ "distanceMultiplier", () => options?.DistanceMultiplier.Value, options?.DistanceMultiplier != null },
634+
{ "distanceField", options?.DistanceField?.Render(outputRenderArgs).FieldName, options?.DistanceField != null },
635+
{ "maxDistance", options?.MaxDistance, options?.MaxDistance != null },
636+
{ "minDistance", options?.MinDistance, options?.MinDistance != null },
637+
{ "distanceMultiplier", options?.DistanceMultiplier, options?.DistanceMultiplier != null },
635638
{ "key", options?.Key, options?.Key != null },
636639
{ "query", options?.Query?.Render(args), options?.Query != null },
637-
{ "includeLocs", options?.IncludeLocs, options?.IncludeLocs != null },
638-
{ "spherical", () => options?.Spherical.Value, options?.Spherical != null }
640+
{ "includeLocs", options?.IncludeLocs?.Render(outputRenderArgs).FieldName, options?.IncludeLocs != null },
641+
{ "spherical", options?.Spherical, options?.Spherical != null }
639642
};
640-
641-
var outputSerializer = args.SerializerRegistry.GetSerializer<TOutput>();
643+
642644
return new RenderedPipelineStageDefinition<TOutput>(operatorName, new BsonDocument(operatorName, geoNearOptions), outputSerializer);
643645
});
644-
646+
645647
return stage;
646648
}
647-
649+
648650
/// <summary>
649651
/// Creates a $geoNear stage.
650652
/// </summary>
@@ -656,31 +658,13 @@ internal static PipelineStageDefinition<TInput, TOutput> GeoNear<TInput, TPoint,
656658
/// <returns>The stage.</returns>
657659
public static PipelineStageDefinition<TInput, TOutput> GeoNear<TInput, TCoordinates, TOutput>(
658660
GeoJsonPoint<TCoordinates> near,
659-
GeoNearOptions<TInput> options = null)
661+
GeoNearOptions<TInput, TOutput> options = null)
660662
where TCoordinates : GeoJsonCoordinates
661663
{
662664
Ensure.IsNotNull(near, nameof(near));
663665
return GeoNear<TInput, GeoJsonPoint<TCoordinates>, TOutput>(near, options);
664666
}
665-
666-
/// <summary>
667-
/// Creates a $geoNear stage.
668-
/// </summary>
669-
/// <typeparam name="TInput">The type of the input documents.</typeparam>
670-
/// <typeparam name="TOutput">The type of the output documents.</typeparam>
671-
/// <typeparam name="TCoordinates">The type of the coordinates for the point.</typeparam>
672-
/// <param name="near">The point for which to find the closest documents.</param>
673-
/// <param name="options">The options.</param>
674-
/// <returns>The stage.</returns>
675-
public static PipelineStageDefinition<TInput, TOutput> GeoNear<TInput, TCoordinates, TOutput>(
676-
TCoordinates[] near,
677-
GeoNearOptions<TInput> options = null)
678-
{
679-
Ensure.IsNotNull(near, nameof(near));
680-
Ensure.That(near.Length, len => len is >= 2 and <= 3, nameof(near), "Legacy coordinates array should have 2 or 3 coordinates.");
681-
return GeoNear<TInput, TCoordinates[], TOutput>(near, options);
682-
}
683-
667+
684668
/// <summary>
685669
/// Creates a $geoNear stage.
686670
/// </summary>
@@ -690,12 +674,12 @@ public static PipelineStageDefinition<TInput, TOutput> GeoNear<TInput, TCoordina
690674
/// <param name="options">The options.</param>
691675
/// <returns>The stage.</returns>
692676
public static PipelineStageDefinition<TInput, TOutput> GeoNear<TInput, TOutput>(
693-
BsonDocument near,
694-
GeoNearOptions<TInput> options = null)
677+
double[] near,
678+
GeoNearOptions<TInput, TOutput> options = null)
695679
{
696680
Ensure.IsNotNull(near, nameof(near));
697-
Ensure.That(near.ElementCount, len => len is >= 2 and <= 3, nameof(near), "Legacy coordinates document should have 2 or 3 coordinates.");
698-
return GeoNear<TInput, BsonDocument, TOutput>(near, options);
681+
Ensure.That(near.Length, len => len is >= 2 and <= 3, nameof(near), "Legacy coordinates array should have 2 or 3 coordinates.");
682+
return GeoNear<TInput, double[], TOutput>(near, options);
699683
}
700684

701685
/// <summary>

0 commit comments

Comments
 (0)