【问题标题】:Replace Root with C# driver for .net core AggregateExpressionDefinition将 Root 替换为 .net core AggregateExpressionDefinition 的 C# 驱动程序
【发布时间】:2019-04-22 14:11:11
【问题描述】:

我正在尝试执行简单的展开并替换 .net core 2.2 中的 root。 我已经在 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 方法可以接收的可能参数之一,但我无法完全理解它。

任何帮助将不胜感激。

【问题讨论】:

    标签: c# asp.net-core mongodb-query


    【解决方案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();
    

    你也可以在之后过滤replace 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"
    }
    

    另外,如果你尝试添加结果类型来替换根 VS 会抛出一个错误,说 lambda 表达式无法转换,因为它不是委托类型。

    这不是(这是我一开始就有的):

    _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();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2019-12-03
        • 2010-10-04
        • 1970-01-01
        • 2019-05-13
        • 2012-09-23
        • 1970-01-01
        • 2021-09-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多