private static void ApplyPredicate <TEntity, TForeign>(AggregateQueryable <TEntity> aggregateQueryable, Expression predicate, string asFieldName) { if (predicate == null) { return; } var foreignType = typeof(TForeign); var isEnumerable = typeof(TForeign).IsEnumerable(); if (isEnumerable) { foreignType = foreignType.GetElementTypeOf(); } //lamb = Expression.Lambda(methodCall.Arguments[0], Expression.Parameter(typeof(TEntity), "p")); var filterDefinitionBuilder = new FilterDefinitionBuilder <TEntity>(); var param1Type = typeof(FieldDefinition <TEntity>); var param2Type = typeof(FilterDefinition <>).MakeGenericType(foreignType); var method = filterDefinitionBuilder.GetType() .GetGenericMethod(nameof(filterDefinitionBuilder.ElemMatch), BindingFlags.Public | BindingFlags.Instance, new[] { foreignType }, new[] { param1Type, param2Type }, typeof(FilterDefinition <TEntity>)); var expressionFilterDefinition = Activator.CreateInstance(typeof(ExpressionFilterDefinition <>).MakeGenericType(foreignType), predicate); var asField = new StringFieldDefinition <TEntity>(asFieldName); var elmMatch = (FilterDefinition <TEntity>)method.Invoke(filterDefinitionBuilder, new object[] { asField, expressionFilterDefinition }); //Filter ($match) elements of TForeign using predicate aggregateQueryable.AggregateFluent = aggregateQueryable.AggregateFluent.Match(elmMatch); }
private static void ApplyLookup <TEntity, TDeclaring, TProperty>(AggregateQueryable <TEntity> aggregateQueryable, MemberInfo navigationMember, string previousNavigationName, out string navigationElementName, out string asFieldName) { var declaringType = typeof(TDeclaring); var propertyType = typeof(TProperty); var isEnumerable = propertyType.IsEnumerable(); if (isEnumerable) { propertyType = propertyType.GetElementTypeOf(); } var associatedMember = AssociatedMemberFinder.GetAssociatedMember(navigationMember); var associatedElementName = associatedMember.GetBsonElementName(); var elementName = navigationMember.Name; navigationElementName = AppendPreviousNavigationName(elementName); asFieldName = AppendPreviousNavigationName(isEnumerable ? elementName : $"__{elementName}__"); var collectioName = CollectionNameFinder.GetCollectionName(propertyType); string localField; string foreignField; var isInside = associatedMember.DeclaringType == declaringType; if (isInside) { localField = AppendPreviousNavigationName(associatedElementName); foreignField = BsonClassMap.LookupClassMap(propertyType).IdMemberMap.ElementName; } else { localField = BsonClassMap.LookupClassMap(declaringType).IdMemberMap.ElementName; foreignField = AppendPreviousNavigationName(associatedElementName); } aggregateQueryable.AggregateFluent = aggregateQueryable.AggregateFluent .Lookup <TProperty, TDeclaring>(collectioName, localField, foreignField, asFieldName) .As <TEntity>(); string AppendPreviousNavigationName(string input) { if (previousNavigationName == null) { return(input); } return(previousNavigationName + "." + input); } }
private static void ApplyProjection <TEntity, TProperty>(AggregateQueryable <TEntity> aggregateQueryable, string asFieldName, string navigationElementName) { var isEnumerable = typeof(TProperty).IsEnumerable(); if (!isEnumerable) { //Set first element as navigation field PipelineStageDefinition <TEntity, TEntity> addFields = "{ \"$addFields\": { \"" + navigationElementName + "\": { \"$arrayElemAt\": [\"$" + asFieldName + "\", 0] } } }"; //Exclude temp @as field PipelineStageDefinition <TEntity, TEntity> project = "{ \"$project\" : { \"" + asFieldName + "\" : 0 } }"; aggregateQueryable.AggregateFluent = aggregateQueryable.AggregateFluent .AppendStage(addFields) .AppendStage(project); } }
public AggregateQueryableIncluded(AggregateQueryable <TEntity> aggregateQueryable, string navigationElementName) : base(aggregateQueryable) { NavigationElementName = navigationElementName.NotNull(nameof(navigationElementName)); }