From 456af09a84490745ded99730484df42cb8eb32f8 Mon Sep 17 00:00:00 2001 From: alexandre-spieser Date: Sun, 5 Aug 2018 21:10:41 +0100 Subject: [PATCH] + Upgraded packages + Added GetByMax, GetByMaxAsync, GetByMin, GetByMinAsync, GetMaxValue and GetMaxValueAsync Methods (GetMinValue and GetMinValueAsync will come in another PR) + Added tests --- CoreIntegrationTests/CRUDPartitionedTests.cs | 1 - .../CoreIntegrationTests.csproj | 19 +- CoreIntegrationTests/IdentityUserTests.cs | 2 +- .../Infrastructure/MongoDbConfig.cs | 2 +- .../Infrastructure/MongoDbDocumentTestBase.cs | 93 +++++++++ .../MongoDbTKeyDocumentTestBase.cs | 136 ++++++++++++ .../Infrastructure/TestClasses.cs | 2 + .../Infrastructure/TestRepository.cs | 22 +- .../Abstractions/IReadOnlyMongoRepository.cs | 114 +++++++++- .../MongoDbGenericRepository.csproj | 2 +- .../MongoDbGenericRepository.nuspec | 6 +- .../ReadOnlyMongoRepository.cs | 196 +++++++++++++++++- 12 files changed, 570 insertions(+), 25 deletions(-) diff --git a/CoreIntegrationTests/CRUDPartitionedTests.cs b/CoreIntegrationTests/CRUDPartitionedTests.cs index 7e0beb1..b743b79 100644 --- a/CoreIntegrationTests/CRUDPartitionedTests.cs +++ b/CoreIntegrationTests/CRUDPartitionedTests.cs @@ -18,7 +18,6 @@ namespace CoreIntegrationTests { public CRUDPartitionedTests(MongoDbTestFixture fixture) : base(fixture) { - } public override string GetClassName() diff --git a/CoreIntegrationTests/CoreIntegrationTests.csproj b/CoreIntegrationTests/CoreIntegrationTests.csproj index 85f6a8d..720179b 100644 --- a/CoreIntegrationTests/CoreIntegrationTests.csproj +++ b/CoreIntegrationTests/CoreIntegrationTests.csproj @@ -5,17 +5,20 @@ - - - - - - - - + + + + + + + + + + + ..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Configuration.dll diff --git a/CoreIntegrationTests/IdentityUserTests.cs b/CoreIntegrationTests/IdentityUserTests.cs index 4554479..5e8b96e 100644 --- a/CoreIntegrationTests/IdentityUserTests.cs +++ b/CoreIntegrationTests/IdentityUserTests.cs @@ -6,7 +6,7 @@ using Xunit; using Microsoft.AspNetCore.Identity; using System.Threading.Tasks; -namespace CoreCoreIntegrationTests +namespace CoreIntegrationTests { public class MongoIdentityUser : IdentityUser, IDocument where TKey : IEquatable diff --git a/CoreIntegrationTests/Infrastructure/MongoDbConfig.cs b/CoreIntegrationTests/Infrastructure/MongoDbConfig.cs index 8964789..4051721 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbConfig.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbConfig.cs @@ -1,4 +1,4 @@ -using CoreCoreIntegrationTests; +using CoreIntegrationTests; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Conventions; using System.Threading; diff --git a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs index be584e7..3137d90 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbDocumentTestBase.cs @@ -679,7 +679,100 @@ namespace CoreIntegrationTests.Infrastructure #endregion Project + #region Max / Min Queries + + [Fact] + public async Task GetByMaxAsync() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMax = documents.OrderByDescending(e => e.Nested.SomeDate).First(); + + // Act + var result = await SUT.GetByMaxAsync(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedMax.Id, result.Id); + } + + [Fact] + public void GetByMax() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMax = documents.OrderByDescending(e => e.Nested.SomeDate).First(); + + // Act + var result = SUT.GetByMax(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedMax.Id, result.Id); + } + + [Fact] + public async Task GetByMinAsync() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMin = documents.OrderBy(e => e.Nested.SomeDate).First(); + + // Act + var result = await SUT.GetByMinAsync(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedMin.Id, result.Id); + } + + [Fact] + public void GetByMin() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMin = documents.OrderBy(e => e.Nested.SomeDate).First(); + + // Act + var result = SUT.GetByMin(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedMin.Id, result.Id); + } + + #endregion Max / Min Queries + #region Test Utils + [MethodImpl(MethodImplOptions.NoInlining)] private string GetCurrentMethod() { diff --git a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs index cb5888c..cc73df6 100644 --- a/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs +++ b/CoreIntegrationTests/Infrastructure/MongoDbTKeyDocumentTestBase.cs @@ -680,6 +680,142 @@ namespace CoreIntegrationTests.Infrastructure #endregion Project + #region Max / Min Queries + + [Fact] + public async Task GetByMaxAsync() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMax = documents.OrderByDescending(e => e.Nested.SomeDate).First(); + + // Act + var result = await SUT.GetByMaxAsync(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedMax.Id, result.Id); + } + + [Fact] + public void GetByMax() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMax = documents.OrderByDescending(e => e.Nested.SomeDate).First(); + + // Act + var result = SUT.GetByMax(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedMax.Id, result.Id); + } + + [Fact] + public void GetMaxValue() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMax = documents.OrderByDescending(e => e.Nested.SomeDate).First(); + + // Act + var result = SUT.GetMaxValue(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.False(result == default(DateTime)); + Assert.Equal(expectedMax.Nested.SomeDate.Date, result.Date); + } + + [Fact] + public async Task GetMaxValueAsync() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMax = documents.OrderByDescending(e => e.Nested.SomeDate).First(); + + // Act + var result = await SUT.GetMaxValueAsync(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.False(result == default(DateTime)); + Assert.Equal(expectedMax.Nested.SomeDate.Date, result.Date); + } + + [Fact] + public async Task GetByMinAsync() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMin = documents.OrderBy(e => e.Nested.SomeDate).First(); + + // Act + var result = await SUT.GetByMinAsync(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedMin.Id, result.Id); + } + + [Fact] + public void GetByMin() + { + // Arrange + var criteria = $"{GetTestName()}.{DocumentTypeName}.{Guid.NewGuid()}"; + var documents = CreateTestDocuments(5); + var i = 1; + documents.ForEach(e => { + e.Nested.SomeDate = e.Nested.SomeDate.AddDays(i++); + e.SomeContent = criteria; + }); + SUT.AddMany(documents); + var expectedMin = documents.OrderBy(e => e.Nested.SomeDate).First(); + + // Act + var result = SUT.GetByMin(e => e.SomeContent == criteria, e => e.Nested.SomeDate, PartitionKey); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedMin.Id, result.Id); + } + + #endregion Max / Min Queries + #region Test Utils [MethodImpl(MethodImplOptions.NoInlining)] private string GetCurrentMethod() diff --git a/CoreIntegrationTests/Infrastructure/TestClasses.cs b/CoreIntegrationTests/Infrastructure/TestClasses.cs index aefb6f6..9727da9 100644 --- a/CoreIntegrationTests/Infrastructure/TestClasses.cs +++ b/CoreIntegrationTests/Infrastructure/TestClasses.cs @@ -47,6 +47,8 @@ namespace CoreIntegrationTests.Infrastructure Children = new List(); } + public int SomeValue { get; set; } + public string SomeContent { get; set; } public int GroupingKey { get; set; } diff --git a/IntegrationTests/Infrastructure/TestRepository.cs b/IntegrationTests/Infrastructure/TestRepository.cs index dbafd3f..f98e83c 100644 --- a/IntegrationTests/Infrastructure/TestRepository.cs +++ b/IntegrationTests/Infrastructure/TestRepository.cs @@ -1,4 +1,9 @@ -using MongoDbGenericRepository; +using MongoDB.Driver; +using MongoDbGenericRepository; +using MongoDbGenericRepository.Models; +using System; +using System.Linq.Expressions; +using System.Threading.Tasks; namespace IntegrationTests.Infrastructure { @@ -18,5 +23,20 @@ namespace IntegrationTests.Infrastructure { MongoDbContext.DropCollection(partitionKey); } + + /// + /// Gets the max of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// + public async Task GetByMaxAsync(Expression> filter, Expression> orderByDescending) + where TDocument : IDocument + where TKey : System.IEquatable + { + return await GetCollection().Find(Builders.Filter.Where(filter)) + .SortByDescending(orderByDescending) + .FirstOrDefaultAsync(); + } } } diff --git a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs index 04036d1..4010e8b 100644 --- a/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/Abstractions/IReadOnlyMongoRepository.cs @@ -111,6 +111,47 @@ namespace MongoDbGenericRepository /// An optional partition key. long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument; + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + /// + TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument; + #endregion #region Read TKey @@ -159,7 +200,6 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable; - /// /// Returns a collection cursor. /// @@ -238,6 +278,78 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable; + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + TValue GetMaxValue(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable; + #endregion } diff --git a/MongoDbGenericRepository/MongoDbGenericRepository.csproj b/MongoDbGenericRepository/MongoDbGenericRepository.csproj index e2f7487..bed1e2f 100644 --- a/MongoDbGenericRepository/MongoDbGenericRepository.csproj +++ b/MongoDbGenericRepository/MongoDbGenericRepository.csproj @@ -17,7 +17,7 @@ - + diff --git a/MongoDbGenericRepository/MongoDbGenericRepository.nuspec b/MongoDbGenericRepository/MongoDbGenericRepository.nuspec index 95efe1b..405505b 100644 --- a/MongoDbGenericRepository/MongoDbGenericRepository.nuspec +++ b/MongoDbGenericRepository/MongoDbGenericRepository.nuspec @@ -2,7 +2,7 @@ MongoDbGenericRepository - 1.3.6 + 1.3.7 MongoDb Generic Repository Alexandre Spieser Alexandre Spieser @@ -10,11 +10,11 @@ https://github.com/alexandre-spieser/mongodb-generic-repository false A generic repository implementation using the MongoDB C# Sharp 2.0 driver. - Adding support for Id of type ObjectId. + Upgraded dependencies. Copyright 2017 (c) Alexandre Spieser. All rights reserved. MongoDb Repository Generic NoSql - + diff --git a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs index 2a4e6f0..5dd5ac2 100644 --- a/MongoDbGenericRepository/ReadOnlyMongoRepository.cs +++ b/MongoDbGenericRepository/ReadOnlyMongoRepository.cs @@ -123,7 +123,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public async Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - var count = await HandlePartitioned(partitionKey).CountAsync(filter); + var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); return (count > 0); } @@ -135,7 +135,7 @@ namespace MongoDbGenericRepository /// An optional partition key. public bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument { - var count = HandlePartitioned(partitionKey).Count(filter); + var count = HandlePartitioned(partitionKey).CountDocuments(filter); return (count > 0); } @@ -169,7 +169,7 @@ namespace MongoDbGenericRepository /// An optional partitionKey public async Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return await HandlePartitioned(partitionKey).CountAsync(filter); + return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); } /// @@ -180,7 +180,68 @@ namespace MongoDbGenericRepository /// An optional partitionKey public long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument { - return HandlePartitioned(partitionKey).Find(filter).Count(); + return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + public async Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + { + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(orderByDescending) + .FirstOrDefaultAsync(); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + /// + public TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(orderByDescending) + .FirstOrDefault(); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public async Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + { + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(orderByAscending) + .FirstOrDefaultAsync(); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(orderByAscending) + .FirstOrDefault(); } #endregion @@ -270,7 +331,7 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable { - var count = await HandlePartitioned(partitionKey).CountAsync(filter); + var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); return (count > 0); } @@ -285,7 +346,7 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable { - var count = HandlePartitioned(partitionKey).Count(filter); + var count = HandlePartitioned(partitionKey).CountDocuments(filter); return (count > 0); } @@ -328,7 +389,7 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable { - return await HandlePartitioned(partitionKey).CountAsync(filter); + return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); } /// @@ -342,7 +403,112 @@ namespace MongoDbGenericRepository where TDocument : IDocument where TKey : IEquatable { - return HandlePartitioned(partitionKey).Find(filter).Count(); + return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + public async Task GetByMaxAsync(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(orderByDescending) + .FirstOrDefaultAsync(); + } + + /// + /// Gets the document with the maximum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by descending. + /// An optional partitionKey. + public TDocument GetByMax(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(orderByDescending) + .FirstOrDefault(); + } + + /// + /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public async Task GetByMinAsync(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(orderByAscending) + .FirstOrDefaultAsync(); + } + + /// + /// Gets the document with the minimum value of a specified property in a MongoDB collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public TDocument GetByMin(Expression> filter, Expression> orderByAscending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortBy(orderByAscending) + .FirstOrDefault(); + } + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public async Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(ConvertExpression(maxValueSelector)) + .Project(maxValueSelector) + .FirstOrDefaultAsync(); + } + + /// + /// Gets the maximum value of a property in a mongodb collections that is satisfying the filter. + /// + /// The document type. + /// The type of the primary key. + /// A LINQ expression filter. + /// A property selector to order by ascending. + /// An optional partitionKey. + public TValue GetMaxValue(Expression> filter, Expression> orderByDescending, string partitionKey = null) + where TDocument : IDocument + where TKey : IEquatable + { + + return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) + .SortByDescending(ConvertExpression(orderByDescending)) + .Project(orderByDescending) + .FirstOrDefault(); } #endregion @@ -450,6 +616,20 @@ namespace MongoDbGenericRepository return GetCollection(); } + /// + /// Converts a LINQ expression of TDocument, TValue to a LINQ expression of TDocument, object + /// + /// The document type. + /// The type of the value. + /// The expression to convert + protected static Expression> ConvertExpression(Expression> expression) + { + var param = expression.Parameters[0]; + Expression body = expression.Body; + var convert = Expression.Convert(body, typeof(object)); + return Expression.Lambda>(convert, param); + } + #endregion }