【问题标题】:What is the C# equivalent of push and root for MongoDB?MongoDB 的 push 和 root 的 C# 等价物是什么?
【发布时间】:2017-06-13 15:28:54
【问题描述】:

我有一群人。我正在尝试为每个名字找到最年长的人。我可以使用 mongoDB 控制台命令实现该结果

db.People.aggregate([
    { '$sort': { 'Name': 1, 'Age': -1 } }, 
    {       
        '$group': {
            '_id': '$Name',
            'docs': { '$push': '$$ROOT' },
        }
    },
    {
        '$project': {
            'top_one': { 
                '$slice': ['$docs', 1]
            }
        }
    } ])

对于 C# 驱动程序来说,这相当于什么?我特别有问题

'docs': { '$push': '$$ROOT' },

这是我当前的 C# 查询:

collection.Aggregate(aggArgs)
   .SortByDescending(x => x.Age) 
   .Group(x => x.Name, x => new { 
       Name = x.First().Name, 
       FavoriteColor = x.First().FavoriteColor, 
       FavoriteFood = x.First().FavoriteFood
    }).ToListAsync().Result;

它的工作方式与我的 mongo 控制台命令的作用很接近,但我真的不喜欢构造匿名对象。我宁愿做Group(x => x.Name,x => x.First()),但是不支持“First()”的抛出和异常。我相信部分问题是我的 Person 类型没有 ID,所以 _id 被放在实际的 mongo 文档上(由 mongo 在插入时自动)。当它尝试返回类型时,它无法进行直接映射。

那么,考虑到查询的两个版本,我如何在 C# 中恢复我的完整类型,而不必拼出每个字段?

【问题讨论】:

    标签: c# .net mongodb mongodb-query mongodb-.net-driver


    【解决方案1】:

    Maksim 让我获得了很多成功。为了得到与我输入的类型相同的类型,我最终得到了以下结果:

    collection.Aggregate(aggArgs)
      .SortByDescending(x => x.Age)
      .Group(new JsonProjectionDefinition<Person>(@"{
         '_id': '$Name',
         'docs': { '$push': '$$ROOT'}
        }"))
      .Project<BsonDocument>(new JsonProjectionDefinition<BsonDocument>(@"{
         'top': { '$slice': ['$docs', 1] }
        }"))
      .Unwind<BsonDocument>(new StringFieldDefinition<BsonDocument>("top"))
      .ReplaceRoot(new BsonValueAggregateExpressionDefinition<BsonDocument, BsonDocument>(@"$top"))
      .Project<Person>(new JsonProjectionDefinition<BsonDocument>(@"{
         _id: 0
        }"))
      .ToList();
    

    【讨论】:

    • 干得好!对我来说,这是一种有点糟糕的方式,我会用 mongo 驱动程序做它允许 t odo 和 linq 休息的事情,但这是你的选择,我不知道你的数据有多大。
    • ReplaceRoot 在某些 mongo 版本中不可用。如果不使用 ReplaceRoot,这个查询会有什么不同?
    【解决方案2】:

    这是 MongoDB 驱动程序的一个特性。它不接受简单的 First(),它背后需要一些东西。这就是我通过调试看到的。所以你应该继续使用 First()... 或者你可以直接查询你的 json:

    var result = collection.Aggregate()                
            .Group(new JsonProjectionDefinition<People>(@" {
                  '_id': '$Name',
                   'docs': { '$push': '$$ROOT' },}"))
            .Project<TopOne>(new JsonProjectionDefinition<BsonDocument>(@"{
                'top_one': { 
                '$slice': ['$docs', 1]
            } }"))
           .ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-08
      • 2011-01-19
      • 2010-12-07
      • 2010-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多