19

Consider the following object structure stored as documents:

public class Foo
{
    public string Id { get; set; }
    public ICollection<FooBar> Bars { get; set; }

    // ...
}

public class FooBar
{
    public string BarId { get; set; }

    // ...
}

Using a LINQ-style query with the driver I can Find all Foo that contain a FooBar BarId like this:

var foos = await m_fooCollection.Find( f => f.Bars.Any( fb => fb.BarId == "123") ).ToListAsync();

How can I achieve this same query using the FilterDefinitionBuilder instead of the in-line LINQ on Find?

5
  • It isn't LINQ, just a lambda expression. Commented Jun 22, 2015 at 17:25
  • .Any on a ICollection is part of the Enumerable class in the System.Linq namespace, right? Commented Jun 22, 2015 at 17:35
  • Indeed, but that method will never be called. The driver translates the expression to a mongo query. Commented Jun 22, 2015 at 17:39
  • Ok, makes sense. I guess I was more trying to express the fact that I am using LINQ style syntax rather than actual LINQ. Commented Jun 22, 2015 at 17:42
  • 1
    Yes, it doesn't really matter. Just a note to future googlers. Commented Jun 22, 2015 at 17:44

1 Answer 1

36

The query you need to perform uses the $elemMatch query operator.

So, this query using a lambda expression

var findFluent = collection.Find(f => f.Bars.Any(fb => fb.BarId == "123"));

Is equivalent to this query using the FilterDefinitionBuilder:

var findFluent = collection.Find(Builders<Foo>.Filter.ElemMatch(
    foo => foo.Bars, 
    foobar => foobar.BarId == "123"));
Sign up to request clarification or add additional context in comments.

6 Comments

What if I have BarNumber property instead of BarId and there are 2 BarNumber with same value. How can I get both of them?
@i3arnon, this returns all the Foo objects that matches the criteria with each object having ALL its FooBar children. What if I need to filter those children objects too (with BarId = "123") so not all FooBar will be present in result?
@benjamin54 I don't think you can do that with a "simple" query. I think you need to use the aggregation framework, but I'm not sure. Maybe you'd be better posing another question...
Hey, if Foo object has a dateTime property, which I want to find by date greaterorequal param, how would you achieve that? Doing like so doesnt work -> var findFluent = collection.Find(Builders<Foo>.Filter.ElemMatch( foo => foo.Bars, foobar => foobar.TimeCreate >= timeParam));
@benjamin54 i am looking for the same answer that you asked. I am late here but looking forward to hear form you! Please let me know if we can do that using FilterDefinitionBuilder ? otherwise projection is the option to do it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.