简体   繁体   English

MongoDB C#驱动程序-仅返回最后修改的行

[英]MongoDB C# Driver - Return last modified rows only

The data: The collection contains a list of audit records and I want to return the last modified items from the collection. 数据:集合包含审计记录列表,我想返回集合中最后修改的项目。

For example: 例如:

审核记录

So the query needs to return Audit 1235 and 1237 Only. 因此,查询仅需要返回Audit 1235和1237。

The following statement works in Mongo Shell and returns the data sub-millisecond, I just need to also figure out how to return the entire Collection item instead of just the Id. 以下语句在Mongo Shell中有效,并返回毫秒级的数据,我只需要弄清楚如何返回整个Collection项而不是Id。

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

However, I need to convert this to the C# Driver's syntax. 但是,我需要将其转换为C#驱动程序的语法。

I have the following at the moment but it's not working and returns (for lack of a better term) weird data (see screencap under the statement). 目前,我有以下内容,但它无法正常工作,并且返回(由于缺少更好的用词)怪异的数据(请参阅声明下方的screencap)。

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

结果

My current solution gets the full collection back and then runs it through an extension method to get the latest records (where list is the full collection): 我当前的解决方案取回完整集合,然后通过扩展方法运行它以获取最新记录(其中列表为完整集合):

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

While this code works, it is EXTREMELY slow because of the sheer amount of data that is being returned from the collection, so I need to do the grouping on the list as part of the collection get/find. 尽管此代码有效,但由于从集合中返回的数据量巨大,速度非常慢,因此,作为集合get / find的一部分,我需要对列表进行分组。

Please let me know if I can provide any additional information. 请让我知道是否可以提供其他信息。

Update: With Axel's help I managed to get it resolved: 更新:在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);

I moved that to it's own method and then use the IDs to get the collection items back, with my projection working as well: 我将其移至它自己的方法,然后使用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();

"filter" in this case is either an Expression or a BsonDocument. 在这种情况下,“过滤器”可以是表达式或BsonDocument。 The performance is great as well - sub-second for the whole thing. 性能也很好-整个过程不到一秒。 Thanks for the help, Axel! 感谢您的帮助,Axel!

I think you're doing an extra OrderBy, this should do: 我认为您要执行额外的OrderBy,这应该可以:

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

EDIT: 编辑:

To gain performance in the query, you could use the Aggregate function differently: 为了在查询中获得性能,可以不同地使用Aggregate函数:

var match = new BsonDocument
{
    {
        "$group",
        new BsonDocument
            {
                { "_id", "$Id"  },
                { "lastModifiedId", new BsonDocument
                    {
                        {
                            "$last", "$_id"
                        }
                    }}
            }
    }
};

var pipeline = new[] { match };
var result = collection.Aggregate(pipeline);

That should be the equivalent of your Mongo Shell query. 那应该相当于您的Mongo Shell查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM