Заменить Root драйвером C # для определения агрегатного выражения .net core

#c# #asp.net-core #mongodb-query

#c# #asp.net-core #mongodb-запрос

Вопрос:

Я пытаюсь выполнить простое развертывание и заменить root в .net core 2.2. Я уже пробовал запрос в MongoDB, и он работает, но мне сложно перевести его на 100% на C # без использования волшебных строк.

Это мой документ:

 {
    "_id" : ObjectId("5cb6475b20b49a5cec99eb89"),
    "name" : "Route A"
    "isActive" : true,
    "buses" : [ 
        {
            "capacity" : "15",
            "time" : "08:00:00",
            "direction" : "Inbound"
        },
        {
            "capacity" : "15",
            "time" : "08:30:00",
            "direction" : "Inbound"
        },
        {
            "capacity" : "15",
            "time" : "08:00:00",
            "direction" : "Outbound"
        },
        {
            "capacity" : "15",
            "time" : "08:30:00",
            "direction" : "Outbound"
        }
    ]
}
  

У меня также есть класс для корневого документа под названием Routes и еще один для вложенного документа под названием Bus.

Запрос, который я запускаю в mongo, является следующим:

 db.routes.aggregate([
    { $match : { "_id" : ObjectId("5cb4e818cb95b3572c8f0f2c") } },
    { $unwind: "$buses" },
    { $replaceRoot: { "newRoot": "$buses" } }
])
  

Ожидаемый результат — простой массив шин, пока я получаю его с помощью этого запроса на C#

 _routes.Aggregate()
                .Match(r => r.Id == routeId)
                .Unwind<Route, UnwoundRoute>(r => r.Buses)
                .ReplaceRoot<Bus>("$buses")
                .ToListAsync();
  

Я хочу знать, возможно ли заменить строку «$ buses» чем-то, что не задано жестко.

Я пытался использовать класс AggregateExpressionDefinition, который является одним из возможных параметров, которые может получить метод ReplaceRoot, но я не смог его полностью понять.

Любая помощь будет оценена.

Ответ №1:

Публикую это здесь на случай, если кто-то в конечном итоге совершит те же ошибки, что и я.

Я в основном создал новый объект «UnwoundRoute» для хранения результатов операции размотки, а затем использовал простое выражение LINQ. Спасибо пользователю reddit u / Nugsly за предложение об изменении способа, которым я должен вызывать unwind.

Это работает:

 _routes.Aggregate()
                .Match(r => r.Id == routeId)
                .Unwind<Route, UnwoundRoute>(r => r.Buses)
                .ReplaceRoot(ur => ur.Buses)
                .ToListAsync();
  

Вы также можете отфильтровать результат замены root впоследствии:

 _routes.Aggregate()
                .Match(r => r.Id == routeId)
                .Unwind<Route, UnwoundRoute>(r => r.Buses)
                .ReplaceRoot(ur => ur.Buses)
                .Match(b => b.Direction == direction)
                .ToListAsync();
  

И он вернет массив документов.

 {
    "capacity" : "15",
    "time" : "08:00:00",
    "direction" : "Inbound"
},
{
    "capacity" : "15",
    "time" : "08:30:00",
    "direction" : "Inbound"
}
  

Кроме того, если вы попытаетесь добавить тип результата для замены root, VS выдаст сообщение об ошибке, в котором говорится, что лямбда-выражение не удалось преобразовать, поскольку оно не является типом делегата.

Это не так (что у меня было в начале):

 _routes.Aggregate()
                .Match(r => r.Id == routeId)
                .Unwind<Route, UnwoundRoute>(r => r.Buses)
                .ReplaceRoot<Bus>(ur => ur.Buses)
                .ToListAsync();
  

Ответ №2:

я могу предложить вам решение, которое использует MongoDAL, который является просто оболочкой вокруг драйвера c #, который скрывает большую часть сложности драйвера.

 using System;
using System.Linq;
using MongoDAL;

namespace BusRoutes
{
    class Route : Entity
    {
        public string name { get; set; }
        public bool isActive { get; set; }
        public Bus[] buses { get; set; }
    }

    class Bus
    {
        public int capacity { get; set; }
        public string time { get; set; }
        public string direction { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new DB("busroutes");

            var routeA = new Route
            {
                name = "Route A",
                buses = new Bus[]
                {
                    new Bus { capacity = 15, direction = "Inbound", time = "8:00:00"},
                    new Bus { capacity = 25, direction = "Outbound", time = "9:00:00" },
                    new Bus { capacity = 35, direction = "Inbound", time = "10:00:00" }
                }
            };

            routeA.Save();

            var query = routeA.Collection()
                .Where(r => r.ID == routeA.ID)
                .SelectMany(r => r.buses);

            Console.WriteLine(query.ToString());

            var busesOfRouteA = query.ToArray();

            foreach (var bus in busesOfRouteA)
            {
                Console.WriteLine(bus.time.ToString());
            }

            Console.ReadKey();
        }
    }
}