Учитывая следующий код C #:
public static class TestMongo
{
public static void Run()
{
var collection = new MongoClient().GetDatabase("TestDb").GetCollection<Foo>("TestCollection");
collection.InsertOne(new Foo()
{
Name = "name1",
SomeArray = new List<Bar>()
{
new Bar() { Field = "LevelA", Value = "value1"},
new Bar() { Field = "LevelA.LevelB", Value = "value2"},
new Bar() { Field = "LevelA.LevelB.LevelC", Value = ""},
new Bar() { Field = "LevelA.LevelD", Value = "value4"},
}
});
}
}
public class Foo
{
public string Name { get; set; }
public List<Bar> SomeArray { get; set; }
}
public class Bar
{
public string Field { get; set; }
public string Value { get; set; }
}
При выполнении метода Run () этот документ вставляется в Mongo:
{
"_id":"5db015375013d8d05aed5c7b",
"Name":"name1",
"SomeArray":[
{"Field":"LevelA","Value":"value1"},
{"Field":"LevelA.LevelB","Value":"value2"},
{"Field":"LevelA.LevelB.LevelC","Value":""},
{"Field":"LevelA.LevelD","Value":"value4"}
]
}
При получении документа я хочу получить только одинмассив элемента путем фильтрации и проецирования его по Field
имени. Пример:
var name = "name1";
var field = "LevelA.LevelB.LevelC";
var filter = Builders<Foo>.Filter.And(
Builders<Foo>.Filter.Eq(w => w.Name, name),
Builders<Foo>.Filter.ElemMatch(x => x.SomeArray, b => b.Field == field));
var projection = Builders<Foo>.Projection.ElemMatch(x => x.SomeArray, b => b.Field == field);
var output = collection.Find(filter).Project(projection).First();
Приведенный выше код работает нормально и возвращает следующий документ:
{
"_id" : ObjectId("5db015275013d8d05aed5c69"),
"SomeArray" : [
{ "Field" : "LevelA.LevelB.LevelC", "Value" : "" }
]
}
Обратите внимание, что поля в массиве представляют иерархию, разделенную точечной нотацией.
Теперь сложная часть: поскольку значение "LevelA.LevelB.LevelC"
пусто, я хочу автоматически получить значение его верхнего уровня "LevelA.LevelB"
, а в случае, если значение "LevelA.LevelB"
также пусто, я хочу, наконец,перейдите к "LevelA"
и вместо этого верните его значение, все в одном запросе динамически.
Я могу придумать способы сделать это с традиционным SQL, но будет ли это достижимо с драйвером MongoDB C #?