18

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?

kspearrin
  • 10,238
  • 9
  • 53
  • 82

1 Answers1

34

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"));
i3arnon
  • 113,022
  • 33
  • 324
  • 344
  • What if I have BarNumber property instead of BarId and there are 2 BarNumber with same value. How can I get both of them? – utaco Jan 26 '17 at 22:57
  • @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 Aug 02 '17 at 11:14
  • @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... – i3arnon Aug 03 '17 at 08:49
  • 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.Filter.ElemMatch( foo => foo.Bars, foobar => foobar.TimeCreate >= timeParam)); – Ben Mar 01 '20 at 14:17
  • what if I need to compare any entire child object like this? Like imagine changing the last part of your query to ... foobar => foobar.child == someobject)) Is this possible? – Urasquirrel Apr 14 '21 at 00:20
  • 1
    @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. – Rizwan Shakir Oct 19 '21 at 17:00