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.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.