public void AstFilter_should_handle_nested_elemMatch() { var ast = AstFilter.ElemMatch( new AstFilterField("Details.A", BsonValueSerializer.Instance), AstFilter.ElemMatch( new AstFilterField("@<elem>", BsonValueSerializer.Instance), AstFilter.Regex(new AstFilterField("DeviceName", BsonValueSerializer.Instance), ".Name0.", ""))); var rendered = ast.Render(); rendered.Should().Be("{ 'Details.A' : { $elemMatch : { $elemMatch : { DeviceName : /.Name0./ } } } }"); }
public static AstFilter Translate(TranslationContext context, MethodCallExpression expression) { if (AllWithContainsInPredicateMethodToFilterTranslator.CanTranslate(expression, out var arrayFieldExpression, out var arrayConstantExpression)) { return(AllWithContainsInPredicateMethodToFilterTranslator.Translate(context, arrayFieldExpression, arrayConstantExpression)); } if (AnyWithContainsInPredicateMethodToFilterTranslator.CanTranslate(expression, out arrayFieldExpression, out arrayConstantExpression)) { return(AnyWithContainsInPredicateMethodToFilterTranslator.Translate(context, arrayFieldExpression, arrayConstantExpression)); } var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(EnumerableMethod.All, EnumerableMethod.Any, EnumerableMethod.AnyWithPredicate)) { var sourceExpression = arguments[0]; var(field, filter) = FilteredEnumerableFilterFieldTranslator.Translate(context, sourceExpression); if (method.IsOneOf(EnumerableMethod.All, EnumerableMethod.AnyWithPredicate)) { var predicateLambda = (LambdaExpression)arguments[1]; var parameterExpression = predicateLambda.Parameters.Single(); var elementSerializer = ArraySerializerHelper.GetItemSerializer(field.Serializer); var parameterSymbol = context.CreateSymbol(parameterExpression, "@<elem>", elementSerializer); // @<elem> represents the implied element var predicateContext = context.WithSingleSymbol(parameterSymbol); // @<elem> is the only symbol visible inside an $elemMatch var predicateFilter = ExpressionToFilterTranslator.Translate(predicateContext, predicateLambda.Body, exprOk: false); filter = AstFilter.Combine(filter, predicateFilter); } if (method.Is(EnumerableMethod.All)) { return(AstFilter.Not(AstFilter.ElemMatch(field, AstFilter.Not(filter)))); } else { if (filter == null) { return(AstFilter.And(AstFilter.Ne(field, BsonNull.Value), AstFilter.Not(AstFilter.Size(field, 0)))); } else { return(AstFilter.ElemMatch(field, filter)); } } } throw new ExpressionNotSupportedException(expression); }
private static AstFilter Translate(TranslationContext context, Expression expression, Expression sourceExpression, Expression itemExpression) { if (itemExpression.NodeType == ExpressionType.Constant) { var sourceField = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression); var itemSerializer = ArraySerializerHelper.GetItemSerializer(sourceField.Serializer); var value = itemExpression.GetConstantValue <object>(containingExpression: expression); var serializedValue = SerializationHelper.SerializeValue(itemSerializer, value); return(AstFilter.ElemMatch(sourceField, AstFilter.Eq(AstFilter.Field("@<elem>", itemSerializer), serializedValue))); // @<elem> represents the implied element } var itemField = ExpressionToFilterFieldTranslator.Translate(context, itemExpression); var sourceValues = sourceExpression.GetConstantValue <IEnumerable>(containingExpression: expression); var serializedValues = SerializationHelper.SerializeValues(itemField.Serializer, sourceValues); return(AstFilter.In(itemField, serializedValues)); }