diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj
index a3ec14a..81ca024 100644
--- a/IntegrationTests/IntegrationTests.csproj
+++ b/IntegrationTests/IntegrationTests.csproj
@@ -63,6 +63,7 @@
+
diff --git a/IntegrationTests/ProjectTests.cs b/IntegrationTests/ProjectTests.cs
new file mode 100644
index 0000000..971fd22
--- /dev/null
+++ b/IntegrationTests/ProjectTests.cs
@@ -0,0 +1,148 @@
+using IntegrationTests.Infrastructure;
+using MongoDbGenericRepository.Models;
+using NUnit.Framework;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace IntegrationTests
+{
+ public class Nested
+ {
+ public DateTime SomeDate { get; set; }
+
+ }
+
+ public class ProjectTestsDocument : Document
+ {
+ public ProjectTestsDocument()
+ {
+ Version = 2;
+ Nested = new Nested
+ {
+ SomeDate = DateTime.UtcNow
+ };
+ }
+
+ public string SomeContent { get; set; }
+
+ public Nested Nested { get; set; }
+ }
+
+ public class ProjectTests : BaseMongoDbRepositoryTests
+ {
+ private class MyProjection
+ {
+ public DateTime SomeDate { get; set; }
+ public string SomeContent { get; set; }
+ }
+
+ [Test]
+ public async Task ProjectOneAsync()
+ {
+ // Arrange
+ const string someContent = "ProjectOneAsyncContent";
+ var someDate = DateTime.UtcNow;
+ var document = CreateTestDocument();
+ document.SomeContent = someContent;
+ document.Nested.SomeDate = someDate;
+ SUT.AddOne(document);
+ // Act
+ var result = await SUT.ProjectOneAsync(
+ x => x.Id == document.Id,
+ x => new MyProjection
+ {
+ SomeContent = x.SomeContent,
+ SomeDate = x.Nested.SomeDate
+ });
+ // Assert
+ Assert.IsNotNull(result);
+ Assert.AreEqual(someContent, result.SomeContent);
+ Assert.AreEqual(someDate.Minute, result.SomeDate.Minute);
+ Assert.AreEqual(someDate.Second, result.SomeDate.Second);
+ }
+
+ [Test]
+ public void ProjectOne()
+ {
+ // Arrange
+ const string someContent = "ProjectOneContent";
+ var someDate = DateTime.UtcNow;
+ var document = CreateTestDocument();
+ document.SomeContent = someContent;
+ document.Nested.SomeDate = someDate;
+ SUT.AddOne(document);
+ // Act
+ var result = SUT.ProjectOne(
+ x => x.Id == document.Id,
+ x => new MyProjection
+ {
+ SomeContent = x.SomeContent,
+ SomeDate = x.Nested.SomeDate
+ });
+ // Assert
+ Assert.IsNotNull(result);
+ Assert.AreEqual(someContent, result.SomeContent);
+ Assert.AreEqual(someDate.Minute, result.SomeDate.Minute);
+ Assert.AreEqual(someDate.Second, result.SomeDate.Second);
+ }
+
+ [Test]
+ public async Task ProjectManyAsync()
+ {
+ // Arrange
+ const string someContent = "ProjectManyAsyncContent";
+ var someDate = DateTime.UtcNow;
+ var document = CreateTestDocuments(5);
+ document.ForEach(e =>
+ {
+ e.SomeContent = someContent;
+ e.Nested.SomeDate = someDate;
+ });
+
+ SUT.AddMany(document);
+ // Act
+ var result = await SUT.ProjectManyAsync(
+ x => x.SomeContent == someContent,
+ x => new MyProjection
+ {
+ SomeContent = x.SomeContent,
+ SomeDate = x.Nested.SomeDate
+ });
+ // Assert
+ Assert.AreEqual(5, result.Count);
+ Assert.AreEqual(someContent, result.First().SomeContent);
+ Assert.AreEqual(someDate.Minute, result.First().SomeDate.Minute);
+ Assert.AreEqual(someDate.Second, result.First().SomeDate.Second);
+ }
+
+ [Test]
+ public void ProjectMany()
+ {
+ // Arrange
+ const string someContent = "ProjectManyContent";
+ var someDate = DateTime.UtcNow;
+ var document = CreateTestDocuments(5);
+ document.ForEach(e =>
+ {
+ e.SomeContent = someContent;
+ e.Nested.SomeDate = someDate;
+ });
+
+ SUT.AddMany(document);
+ // Act
+ var result = SUT.ProjectMany(
+ x => x.SomeContent == someContent,
+ x => new MyProjection
+ {
+ SomeContent = x.SomeContent,
+ SomeDate = x.Nested.SomeDate
+ });
+ // Assert
+ Assert.AreEqual(5, result.Count);
+ Assert.AreEqual(someContent, result.First().SomeContent);
+ Assert.AreEqual(someDate.Minute, result.First().SomeDate.Minute);
+ Assert.AreEqual(someDate.Second, result.First().SomeDate.Second);
+ }
+ }
+}
diff --git a/MongoDbGenericRepository/MongoDbRepository.cs b/MongoDbGenericRepository/MongoDbRepository.cs
index f00ff93..ba44ee4 100644
--- a/MongoDbGenericRepository/MongoDbRepository.cs
+++ b/MongoDbGenericRepository/MongoDbRepository.cs
@@ -227,6 +227,58 @@ namespace MongoDbGenericRepository
#endregion
+ #region Project
+
+ ///
+ /// Asynchronously returns a projected document matching the filter condition.
+ ///
+ ///
+ ///
+ ///
+ /// The projection expression.
+ /// An optional partition key.
+ Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null)
+ where TDocument : IDocument
+ where TProjection : class;
+
+ ///
+ /// Returns a projected document matching the filter condition.
+ ///
+ ///
+ ///
+ ///
+ /// The projection expression.
+ /// An optional partition key.
+ TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null)
+ where TDocument : IDocument
+ where TProjection : class;
+
+ ///
+ /// Asynchronously returns a list of projected documents matching the filter condition.
+ ///
+ ///
+ ///
+ ///
+ /// The projection expression.
+ /// An optional partition key.
+ Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null)
+ where TDocument : IDocument
+ where TProjection : class;
+
+ ///
+ /// Asynchronously returns a list of projected documents matching the filter condition.
+ ///
+ ///
+ ///
+ ///
+ /// The projection expression.
+ /// An optional partition key.
+ List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null)
+ where TDocument : IDocument
+ where TProjection : class;
+
+ #endregion
+
}
///
@@ -577,27 +629,77 @@ namespace MongoDbGenericRepository
#endregion Delete
- #region Projection
+ #region Project
///
- /// Asynchronously returns a list of projected document matching the filter condition.
+ /// Asynchronously returns a projected document matching the filter condition.
///
///
///
///
/// The projection expression.
/// An optional partition key.
- public async Task GetProjectedAsync(Expression> filter, Expression> projection, string partitionKey = null)
+ public async Task ProjectOneAsync(Expression> filter, Expression> projection, string partitionKey = null)
where TDocument : IDocument
- where TProjection : class, new()
+ where TProjection : class
{
return await HandlePartitioned(partitionKey).Find(filter)
.Project(projection)
.FirstOrDefaultAsync();
}
- #endregion
+ ///
+ /// Returns a projected document matching the filter condition.
+ ///
+ ///
+ ///
+ ///
+ /// The projection expression.
+ /// An optional partition key.
+ public TProjection ProjectOne(Expression> filter, Expression> projection, string partitionKey = null)
+ where TDocument : IDocument
+ where TProjection : class
+ {
+ return HandlePartitioned(partitionKey).Find(filter)
+ .Project(projection)
+ .FirstOrDefault();
+ }
+ ///
+ /// Asynchronously returns a list of projected documents matching the filter condition.
+ ///
+ ///
+ ///
+ ///
+ /// The projection expression.
+ /// An optional partition key.
+ public async Task> ProjectManyAsync(Expression> filter, Expression> projection, string partitionKey = null)
+ where TDocument : IDocument
+ where TProjection : class
+ {
+ return await HandlePartitioned(partitionKey).Find(filter)
+ .Project(projection)
+ .ToListAsync();
+ }
+
+ ///
+ /// Asynchronously returns a list of projected documents matching the filter condition.
+ ///
+ ///
+ ///
+ ///
+ /// The projection expression.
+ /// An optional partition key.
+ public List ProjectMany(Expression> filter, Expression> projection, string partitionKey = null)
+ where TDocument : IDocument
+ where TProjection : class
+ {
+ return HandlePartitioned(partitionKey).Find(filter)
+ .Project(projection)
+ .ToList();
+ }
+
+ #endregion
///
/// Asynchronously returns a paginated list of the documents matching the filter condition.