using MongoDB.Driver; using MongoDB.Driver.Linq; using MongoDbGenericRepository.DataAccess.Base; using MongoDbGenericRepository.Models; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; namespace MongoDbGenericRepository.DataAccess.Read { public partial class MongoDbReader : DataAccessBase { public MongoDbReader(IMongoDbContext mongoDbContext) : base(mongoDbContext) { } #region Read TKey /// /// Asynchronously returns one document given its id. /// /// The type representing a Document. /// The type of the primary key for a Document. /// The Id of the document you want to get. /// An optional partition key. public async virtual Task GetByIdAsync(TKey id, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { var filter = Builders.Filter.Eq("Id", id); return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); } /// /// Returns one document given its id. /// /// The type representing a Document. /// The type of the primary key for a Document. /// The Id of the document you want to get. /// An optional partition key. public virtual TDocument GetById(TKey id, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { var filter = Builders.Filter.Eq("Id", id); return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); } /// /// Asynchronously returns one document given an expression filter. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. public async virtual Task GetOneAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await HandlePartitioned(partitionKey).Find(filter).FirstOrDefaultAsync(); } /// /// Returns one document given an expression filter. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. public virtual TDocument GetOne(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(filter).FirstOrDefault(); } /// /// Returns a collection cursor. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. public virtual IFindFluent GetCursor(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(filter); } /// /// Returns true if any of the document of the collection matches the filter condition. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. public async virtual Task AnyAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { var count = await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); return (count > 0); } /// /// Returns true if any of the document of the collection matches the filter condition. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. public virtual bool Any(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { var count = HandlePartitioned(partitionKey).CountDocuments(filter); return (count > 0); } /// /// Asynchronously returns a list of the documents matching the filter condition. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. public async virtual Task> GetAllAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await HandlePartitioned(partitionKey).Find(filter).ToListAsync(); } /// /// Returns a list of the documents matching the filter condition. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partition key. public virtual List GetAll(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(filter).ToList(); } /// /// Asynchronously counts how many documents match the filter condition. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partitionKey public async virtual Task CountAsync(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await HandlePartitioned(partitionKey).CountDocumentsAsync(filter); } /// /// Counts how many documents match the filter condition. /// /// The type representing a Document. /// The type of the primary key for a Document. /// A LINQ expression filter. /// An optional partitionKey public virtual long Count(Expression> filter, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return HandlePartitioned(partitionKey).Find(filter).CountDocuments(); } #endregion #region Min / Max /// /// 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 virtual Task GetByMaxAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) .SortByDescending(maxValueSelector) .Limit(1) .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 virtual TDocument GetByMax(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) .SortByDescending(maxValueSelector) .Limit(1) .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 virtual Task GetByMinAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) .SortBy(minValueSelector) .Limit(1) .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 virtual TDocument GetByMin(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return GetCollection(partitionKey).Find(Builders.Filter.Where(filter)) .SortBy(minValueSelector) .Limit(1) .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 virtual Task GetMaxValueAsync(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await GetMaxMongoQuery(filter, maxValueSelector, partitionKey) .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. /// The type of the value used to order the query. /// A LINQ expression filter. /// A property selector to order by ascending. /// An optional partitionKey. public virtual TValue GetMaxValue(Expression> filter, Expression> maxValueSelector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return GetMaxMongoQuery(filter, maxValueSelector, partitionKey) .Project(maxValueSelector) .FirstOrDefault(); } /// /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. /// /// The document type. /// The type of the primary key. /// The type of the value used to order the query. /// A LINQ expression filter. /// A property selector to order by ascending. /// An optional partition key. public virtual async Task GetMinValueAsync(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefaultAsync(); } /// /// Gets the minimum value of a property in a mongodb collections that is satisfying the filter. /// /// The document type. /// The type of the primary key. /// The type of the value used to order the query. /// A LINQ expression filter. /// A property selector to order by ascending. /// An optional partition key. public virtual TValue GetMinValue(Expression> filter, Expression> minValueSelector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return GetMinMongoQuery(filter, minValueSelector, partitionKey).Project(minValueSelector).FirstOrDefault(); } #endregion Min / Max #region Sum TKey /// /// Sums the values of a selected field for a given filtered collection of documents. /// /// The type representing a Document. /// A LINQ expression filter. /// The field you want to sum. /// The partition key of your document, if any. public virtual async Task SumByAsync(Expression> filter, Expression> selector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await GetQuery(filter, partitionKey).SumAsync(selector); } /// /// Sums the values of a selected field for a given filtered collection of documents. /// /// The type representing a Document. /// A LINQ expression filter. /// The field you want to sum. /// The partition key of your document, if any. public virtual int SumBy(Expression> filter, Expression> selector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return GetQuery(filter, partitionKey).Sum(selector); } /// /// Sums the values of a selected field for a given filtered collection of documents. /// /// The type representing a Document. /// A LINQ expression filter. /// The field you want to sum. /// The partition key of your document, if any. public virtual async Task SumByAsync(Expression> filter, Expression> selector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return await GetQuery(filter, partitionKey).SumAsync(selector); } /// /// Sums the values of a selected field for a given filtered collection of documents. /// /// The type representing a Document. /// A LINQ expression filter. /// The field you want to sum. /// The partition key of your document, if any. public virtual decimal SumBy(Expression> filter, Expression> selector, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable { return GetQuery(filter, partitionKey).Sum(selector); } #endregion Sum TKey } public partial class MongoDbReader { /// /// Groups a collection of documents given a grouping criteria, /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. /// /// The type representing a Document. /// The type of the grouping criteria. /// The type of the projected group. /// The grouping criteria. /// The projected group result. /// The partition key of your document, if any. public virtual List GroupBy( Expression> groupingCriteria, Expression, TProjection>> groupProjection, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable where TProjection : class, new() { return HandlePartitioned(partitionKey) .Aggregate() .Group(groupingCriteria, groupProjection) .ToList(); } /// /// Groups filtered a collection of documents given a grouping criteria, /// and returns a dictionary of listed document groups with keys having the different values of the grouping criteria. /// /// The type representing a Document. /// The type of the grouping criteria. /// The type of the projected group. /// A LINQ expression filter. /// The grouping criteria. /// The projected group result. /// The partition key of your document, if any. public virtual List GroupBy( Expression> filter, Expression> selector, Expression, TProjection>> projection, string partitionKey = null) where TDocument : IDocument where TKey : IEquatable where TProjection : class, new() { var collection = HandlePartitioned(partitionKey); return collection.Aggregate() .Match(Builders.Filter.Where(filter)) .Group(selector, projection) .ToList(); } } }