private void TranslateOrderBy(OrderByExpression node) { Translate(node.Source); BsonDocument sort = new BsonDocument(); foreach (var clause in node.Clauses) { var field = FieldExpressionFlattener.FlattenFields(clause.Expression) as IFieldExpression; if (field == null) { throw new NotSupportedException("Only fields are allowed in a $sort."); } var direction = clause.Direction == SortDirection.Ascending ? 1 : -1; if (sort.Contains(field.FieldName)) { var message = string.Format("Redundant ordering fields are not supported: {0}.", field.FieldName); throw new NotSupportedException(message); } sort.Add(field.FieldName, direction); } _stages.Add(new BsonDocument("$sort", sort)); }
public static RenderedProjectionDefinition <TProjection> Translate <TDocument, TProjection>(Expression <Func <TDocument, TProjection> > projector, IBsonSerializer <TDocument> parameterSerializer, IBsonSerializerRegistry serializerRegistry) { var bindingContext = new PipelineBindingContext(serializerRegistry); var documentExpression = new DocumentExpression(parameterSerializer); bindingContext.AddExpressionMapping(projector.Parameters[0], documentExpression); var node = PartialEvaluator.Evaluate(projector.Body); node = Transformer.Transform(node); node = bindingContext.Bind(node, isClientSideProjection: true); node = FieldExpressionFlattener.FlattenFields(node); BsonDocument projectionDocument = null; IBsonSerializer <TProjection> serializer; if (node is DocumentExpression) { serializer = new ProjectingDeserializer <TDocument, TProjection>(parameterSerializer, projector.Compile()); } else { var candidateFields = SerializationExpressionGatherer.Gather(node); var fields = GetUniqueFieldsByHierarchy(candidateFields); var serializationInfo = fields.Select(x => new BsonSerializationInfo(x.FieldName, x.Serializer, x.Serializer.ValueType)).ToList(); var projectedObjectExpression = Expression.Parameter(typeof(ProjectedObject), "document"); var translator = new FindProjectionTranslator(documentExpression, projectedObjectExpression, fields); var translated = translator.Visit(node); if (translator._fullDocument) { serializer = new ProjectingDeserializer <TDocument, TProjection>(parameterSerializer, projector.Compile()); } else { var newProjector = Expression.Lambda <Func <ProjectedObject, TProjection> >( translated, projectedObjectExpression); projectionDocument = GetProjectionDocument(serializationInfo); var projectedObjectSerializer = new ProjectedObjectDeserializer(serializationInfo); serializer = new ProjectingDeserializer <ProjectedObject, TProjection>(projectedObjectSerializer, newProjector.Compile()); } } return(new RenderedProjectionDefinition <TProjection>(projectionDocument, serializer)); }
private DocumentExpression BuildProjector(PipelineBindingContext bindingContext, Expression idSelector, Expression elementSelector) { var elementSerializer = bindingContext.GetSerializer(elementSelector.Type, elementSelector); var flattenedElementField = FieldExpressionFlattener.FlattenFields(elementSelector); var elementFieldName = (flattenedElementField as IFieldExpression)?.FieldName; var serializerType = typeof(GroupingDeserializer <,>).MakeGenericType( idSelector.Type, elementSelector.Type); var serializer = (IBsonSerializer)Activator.CreateInstance( serializerType, bindingContext.GetSerializer(idSelector.Type, idSelector), bindingContext.GetSerializer(elementSelector.Type, elementSelector), elementFieldName); return(new DocumentExpression(serializer)); }
/// <inheritdoc /> public override RenderedFieldDefinition Render(IBsonSerializer <TDocument> documentSerializer, IBsonSerializerRegistry serializerRegistry) { var bindingContext = new PipelineBindingContext(serializerRegistry); var lambda = ExpressionHelper.GetLambda(PartialEvaluator.Evaluate(_expression)); var parameterExpression = new DocumentExpression(documentSerializer); bindingContext.AddExpressionMapping(lambda.Parameters[0], parameterExpression); var bound = bindingContext.Bind(lambda.Body); bound = FieldExpressionFlattener.FlattenFields(bound); IFieldExpression field; if (!ExpressionHelper.TryGetExpression(bound, out field)) { var message = string.Format("Unable to determine the serialization information for {0}.", _expression); throw new InvalidOperationException(message); } return(new RenderedFieldDefinition(field.FieldName, field.Serializer)); }