Skip to content

CSHARP-5505: Add $geoNear stage aggregation builders #1621

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

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
190 changes: 0 additions & 190 deletions src/MongoDB.Driver/Core/Operations/GeoNearOperation.cs

This file was deleted.

71 changes: 71 additions & 0 deletions src/MongoDB.Driver/GeoNearOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* Copyright 2010-present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using MongoDB.Bson.Serialization;

namespace MongoDB.Driver
{
/// <summary>
/// Represents options for the $geoNear stage.
/// </summary>
public class GeoNearOptions<TInputDocument, TOutputDocument>
{
/// <summary>
/// Gets or sets the output field that contains the calculated distance. Required if querying a time-series collection.
/// Optional for non-time series collections in MongoDB 8.1+
/// </summary>
public FieldDefinition<TOutputDocument> DistanceField { get; set; }

/// <summary>
/// Gets or sets the factor to multiply all distances returned by the query.
/// </summary>
public double? DistanceMultiplier { get; set; }

/// <summary>
/// Gets or sets the output field that identifies the location used to calculate the distance.
/// </summary>
public FieldDefinition<TOutputDocument> IncludeLocs { get; set; }

/// <summary>
/// Gets or sets the geospatial indexed field used when calculating the distance.
/// </summary>
public string Key { get; set; }

/// <summary>
/// Gets or sets the max distance from the center point that the documents can be.
/// </summary>
public double? MaxDistance { get; set; }

/// <summary>
/// Gets or sets the min distance from the center point that the documents can be.
/// </summary>
public double? MinDistance { get; set; }

/// <summary>
/// Gets or sets the output serializer.
/// </summary>
public IBsonSerializer<TOutputDocument> OutputSerializer { get; set; }

/// <summary>
/// Gets or sets the query that limits the results to the documents that match the query.
/// </summary>
public FilterDefinition<TInputDocument> Query { get; set; }

/// <summary>
/// Gets or sets the spherical option which determines how to calculate the distance between two points.
/// </summary>
public bool? Spherical { get; set; }
}
}
39 changes: 39 additions & 0 deletions src/MongoDB.Driver/IAggregateFluentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Driver.Core.Misc;
using MongoDB.Driver.GeoJsonObjectModel;

namespace MongoDB.Driver
{
Expand Down Expand Up @@ -252,6 +253,44 @@ public static IAggregateFluent<TNewResult> Facet<TResult, TNewResult>(
return aggregate.AppendStage(PipelineStageDefinitionBuilder.Facet<TResult, TNewResult>(facets));
}

/// <summary>
/// Appends a $geoNear stage to the pipeline.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <typeparam name="TNewResult">The type of the new result.</typeparam>
/// <typeparam name="TCoordinates">The type of the coordinates for the point.</typeparam>
/// <param name="aggregate">The aggregate.</param>
/// <param name="near">The point for which to find the closest documents.</param>
/// <param name="options">The options.</param>
/// <returns>The fluent aggregate interface.</returns>
public static IAggregateFluent<TNewResult> GeoNear<TResult, TCoordinates, TNewResult>(
this IAggregateFluent<TResult> aggregate,
GeoJsonPoint<TCoordinates> near,
GeoNearOptions<TResult, TNewResult> options = null)
where TCoordinates : GeoJsonCoordinates
{
Ensure.IsNotNull(aggregate, nameof(aggregate));
return aggregate.AppendStage(PipelineStageDefinitionBuilder.GeoNear<TResult, GeoJsonPoint<TCoordinates>, TNewResult>(near, options));
}

/// <summary>
/// Appends a $geoNear stage to the pipeline.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <typeparam name="TNewResult">The type of the new result.</typeparam>
/// <param name="aggregate">The aggregate.</param>
/// <param name="near">The point for which to find the closest documents.</param>
/// <param name="options">The options.</param>
/// <returns>The fluent aggregate interface.</returns>
public static IAggregateFluent<TNewResult> GeoNear<TResult, TNewResult>(
this IAggregateFluent<TResult> aggregate,
double[] near,
GeoNearOptions<TResult, TNewResult> options = null)
{
Ensure.IsNotNull(aggregate, nameof(aggregate));
return aggregate.AppendStage(PipelineStageDefinitionBuilder.GeoNear<TResult, TNewResult>(near, options));
}

/// <summary>
/// Appends a $graphLookup stage to the pipeline.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public AstGeoNearStage(
string key)
{
_near = Ensure.IsNotNull(near, nameof(near));
_distanceField = Ensure.IsNotNull(distanceField, nameof(distanceField));
_distanceField = distanceField;
_spherical = spherical;
_maxDistance = maxDistance;
_query = query;
Expand Down Expand Up @@ -80,7 +80,7 @@ public override BsonValue Render()
{ "$geoNear", new BsonDocument
{
{ "near", _near },
{ "distanceField", _distanceField },
{ "distanceField", _distanceField, _distanceField != null },
{ "spherical", () => _spherical.Value, _spherical.HasValue },
{ "maxDistance", () => _maxDistance.Value, _maxDistance.HasValue },
{ "query", _query, _query != null },
Expand Down
41 changes: 41 additions & 0 deletions src/MongoDB.Driver/PipelineDefinitionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Driver.Core.Misc;
using MongoDB.Driver.GeoJsonObjectModel;
using MongoDB.Driver.Search;

namespace MongoDB.Driver
Expand Down Expand Up @@ -484,6 +485,46 @@ public static PipelineDefinition<TInput, TInput> For<TInput>(IBsonSerializer<TIn
return new EmptyPipelineDefinition<TInput>(inputSerializer);
}

/// <summary>
/// Appends a $geoNear stage to the pipeline.
/// </summary>
/// <typeparam name="TInput">The type of the input documents.</typeparam>
/// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
/// <typeparam name="TOutput">The type of the output documents.</typeparam>
/// <typeparam name="TCoordinates">The type of the coordinates for the point.</typeparam>
/// <param name="pipeline">The pipeline.</param>
/// <param name="near">The point for which to find the closest documents.</param>
/// <param name="options">The options.</param>
/// <returns>A new pipeline with an additional stage.</returns>
public static PipelineDefinition<TInput, TOutput> GeoNear<TInput, TIntermediate, TCoordinates, TOutput>(
this PipelineDefinition<TInput, TIntermediate> pipeline,
GeoJsonPoint<TCoordinates> near,
GeoNearOptions<TIntermediate, TOutput> options = null)
where TCoordinates : GeoJsonCoordinates
{
Ensure.IsNotNull(pipeline, nameof(pipeline));
return pipeline.AppendStage(PipelineStageDefinitionBuilder.GeoNear(near, options));
}

/// <summary>
/// Appends a $geoNear stage to the pipeline.
/// </summary>
/// <typeparam name="TInput">The type of the input documents.</typeparam>
/// <typeparam name="TIntermediate">The type of the intermediate documents.</typeparam>
/// <typeparam name="TOutput">The type of the output documents.</typeparam>
/// <param name="pipeline">The pipeline.</param>
/// <param name="near">The point for which to find the closest documents.</param>
/// <param name="options">The options.</param>
/// <returns>A new pipeline with an additional stage.</returns>
public static PipelineDefinition<TInput, TOutput> GeoNear<TInput, TIntermediate, TOutput>(
this PipelineDefinition<TInput, TIntermediate> pipeline,
double[] near,
GeoNearOptions<TIntermediate, TOutput> options = null)
{
Ensure.IsNotNull(pipeline, nameof(pipeline));
return pipeline.AppendStage(PipelineStageDefinitionBuilder.GeoNear(near, options));
}

/// <summary>
/// Appends a $graphLookup stage to the pipeline.
/// </summary>
Expand Down
Loading