【问题标题】:MongoDB C# Driver - Return last modified rows onlyMongoDB C# 驱动程序 - 仅返回最后修改的行
【发布时间】:2016-09-27 11:37:57
【问题描述】:

数据: 集合包含审计记录列表,我想从集合中返回最后修改的项目。

例如:

所以查询只需要返回 Audit 1235 和 1237。

以下语句在 Mongo Shell 中工作并返回亚毫秒级的数据,我只需要弄清楚如何返回整个 Collection 项目而不仅仅是 Id。

db.Forms.aggregate(
{ $group: { _id: "$Id", lastModifiedId: { $last: "$_id" } } }
)

但是,我需要将其转换为 C# 驱动程序的语法。

我目前有以下内容,但它不起作用并返回(由于缺乏更好的术语)奇怪的数据(请参阅声明下的屏幕截图)。

var results = collection.Aggregate()
.Group(new BsonDocument { { "_id", "$Id" }, { "lastModifiedId", new BsonDocument("$last", "_id") } })
.ToListAsync().Result.ToList();

我当前的解决方案取回完整集合,然后通过扩展方法运行它以获取最新记录(其中 list 是完整集合):

var lastModifiedOnlyList =
from listItem in list.OrderByDescending(_ => _.AuditId)
group listItem by listItem.Id into grp
select grp.OrderByDescending(listItem => listItem.AuditId)
.FirstOrDefault();

虽然此代码有效,但由于从集合返回的数据量巨大,它非常慢,因此我需要在列表中进行分组作为集合获取/查找的一部分。

如果我可以提供任何其他信息,请告诉我。

更新:在 Axel 的帮助下,我设法解决了这个问题:

var pipeline = new[] { new BsonDocument { { "$group", new BsonDocument { { "_id", "$Id" }, { "LastAuditId", new BsonDocument { { "$last", "$_id" } } } } } } };
var lastAuditIds = collection.Aggregate<Audit>(pipeline).ToListAsync().Result.ToList().Select(_=>_.LastAuditId);

我将它移到它自己的方法中,然后使用 ID 来取回集合项目,我的投影也可以正常工作:

var forLastAuditIds = ForLastAuditIds(collection);

var limitedList = (
                projection != null
                    ? collection.Find(forLastAuditIds & filter, new FindOptions()).Project(projection)
                    : collection.Find(forLastAuditIds & filter, new FindOptions())
            ).ToListAsync().Result.ToList();

在这种情况下,“过滤器”是一个表达式或一个 BsonDocument。性能也很棒 - 整个事情都在亚秒级。感谢您的帮助,阿克塞尔!

【问题讨论】:

    标签: c# mongodb


    【解决方案1】:

    我认为您正在做一个额外的 OrderBy,应该这样做:

    var lastModifiedOnlyList =
    from listItem in list
    group listItem by listItem.Id into grp
    select grp.OrderByDescending(listItem => listItem.AuditId)
    .FirstOrDefault();
    

    编辑:

    为了在查询中获得性能,您可以不同地使用 Aggregate 函数:

    var match = new BsonDocument
    {
        {
            "$group",
            new BsonDocument
                {
                    { "_id", "$Id"  },
                    { "lastModifiedId", new BsonDocument
                        {
                            {
                                "$last", "$_id"
                            }
                        }}
                }
        }
    };
    
    var pipeline = new[] { match };
    var result = collection.Aggregate(pipeline);
    

    这应该相当于您的 Mongo Shell 查询。

    【讨论】:

    • 嗨,阿克塞尔,感谢您提供的信息。我已经用你的建议更新了我的代码,虽然它已经有了如此轻微的改进,但它仍然需要很长时间,因此需要将组移动到 Collection 得到,而不是我现在这样做的方式。放慢速度的不是这个组,而是当前需要很长时间才能返回的 Collection 获取,即 collection.Find(filter, new FindOptions())
    • @JohannMarx 我已经编辑了答案。请确认它是否适合您。
    • 阿克塞尔,成功了,谢谢! :) 我现在正在获取 ID 和最新的审计 ID(根据 Mongo Shell 查询),我现在唯一需要的是获取整个 Collection 项目,即该审计 ID 的相应表单。而且它又好又快! :)
    • @JohannMarx:太好了。感谢您让我知道它有效:)。请您选择我的答案作为正确答案吗?将不胜感激。
    • 肯定会的!它确实帮助我取回最新记录的 ID,关于如何取回实际的 Collection Item 而不仅仅是 ID 的任何建议?如果不可能,这不是问题,我可以使用该审核 ID 列表再次查询集合并取回这些项目。再次感谢您的帮助,不胜感激!
    猜你喜欢
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 2015-09-01
    相关资源
    最近更新 更多