Boas Enkler
Boas Enkler

Reputation: 12557

MongoDb passing predicate argument

in MongoDb I can pass a predicate to an queryable instance for example

DataBase.GetCollection<BsonDocument>("entity")
    .AsQueryable<Entity>()
    .Where(item=>item.id ==5);

But now I have function like this

IEnumerbale QueryData(Predicate<Entity> condition)
{
    this.DataBase.GetCollection<BsonDocument>("entity")
        .AsQueryable<Entity>()
        .Where(item=> condition(item));
}

but this does not work and tells me:

Unsupported where clause: .

Is this as designed? is there any workaround ? Am I doing something wrong?

Upvotes: 1

Views: 2234

Answers (3)

piyush gupta
piyush gupta

Reputation: 111

Pass Lambda expression as parameter to filter data from mongodb collection. Your data filter function could be

public IEnumerable<BsonDocument> FindAllWithPredicate(Func<BsonDocument, bool> condition)
{
    return Collection.AsQueryable().Where(condition).ToArray();
}

Predicatebuilder.cs

public static class PredicateBuilder
{
    public static Expression<Func<T, bool>> True<T>()
    {
        return f => true;
    }

    public static Expression<Func<T, bool>> False<T>()
    {
        return f => false;
    }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>
            (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
    }

    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>
            (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
    }
}   

Generate lambda expression by predicate builder

public static class PredicateBuilderStore
{
    public static Func<BsonDocument, bool> GetPredicateForBsonDocument(Entity entity)
    {
        var predicate = PredicateBuilder.True<BsonDocument>();            
        predicate = predicate.And(d => d.GetElement({key}).Value == CompareWithValue);
        return predicate.Compile();
    }   
}

if you want to query just all items, you could do it as:

return this.collection.Find(_=>true).ToArray();

Upvotes: 0

usr
usr

Reputation: 171236

You're not even passing an expression. Your condition is a totally opaque function to MongoDB.

You need to pass in an Expression<Func<Entity,bool>> and call Where like this:

Where(condition)

Upvotes: 4

Robert Stam
Robert Stam

Reputation: 12187

The Where clause must be translated to a MongoDB query that is sent to the server. When you pass in an arbitrary Predicate like that the LINQ layer has no idea what to translate it to. So that type of open-ended Where clause can't be supported.

Upvotes: 2

Related Questions