3

Рассмотрим следующую структуру объекта хранится в виде документов:Запрос с фильтром строителем на вложенном массиве с использованием MongoDB C драйвер #

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

    // ... 
} 

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

    // ... 
} 

с помощью запроса LINQ-стиле с водителем я могу Find все Foo, которые содержат FooBarBarId как это:

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

Как я могу добиться этого же запроса с использованием FilterDefinitionBuilder вместо поточного LINQ на Find?

+0

Это не LINQ, просто лямбда-выражение. – i3arnon

+0

'.Any' на' ICollection' является частью класса 'Enumerable' в пространстве имен' System.Linq', правильно? – kspearrin

+0

Действительно, но этот метод никогда не будет называться. Драйвер переводит выражение в запрос mongo. – i3arnon

ответ

6

Запрос, который необходимо выполнить, использует оператор запроса $elemMatch.

Таким образом, этот запрос с использованием лямбда-выражения

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

эквивалентно этому запросу с помощью FilterDefinitionBuilder:

var findFluent = collection.Find(Builders<Foo>.Filter.ElemMatch(
    foo => foo.Bars, 
    foobar => foobar.BarId == "123")); 
+0

Что делать, если у меня есть свойство BarNumber вместо BarId, и есть 2 BarNumber с одинаковым значением. Как я могу получить их обоих? – umtc

+0

@ i3arnon, это возвращает все объекты 'Foo', которые соответствуют критериям, при этом каждый объект имеет ВСЕ его дочерние элементы FooBar. Что делать, если мне нужно также фильтровать эти дочерние объекты (с 'BarId =" 123 "'), поэтому не все FooBar будут присутствовать в результате? – benjamin54

+0

@ benjamin54 Я не думаю, что вы можете сделать это с помощью «простого» запроса. Я думаю, вам нужно использовать структуру агрегации, но я не уверен. Может быть, вам лучше задать другой вопрос ... – i3arnon