按2个字段的总和和降序排序数据

本文关键字:降序 数据 排序 2个 字段 | 更新日期: 2023-09-27 18:20:15

我在MongoDB 中收集了此文档

string _id;
string item;
string category;
int mobileView;
int webView;

我想取10个项目,按mobileViewwebView的总和降序排列,我是否可以通过查询直接实现这一点,或者我应该获取所有数据并循环所有数据,手动求和mobileViewwebView,然后只取总数最高的10个?

我一直在读关于Aggregation Framework的文章,但据我所知,它Sum只是一个由查询分组的字段。做了我所理解的是错误的,如果是的话,如何使用Aggregation Framework来做。

(我不希望View的总Sum被同一个category分组,在排序之前,我只需要每个项目上的SumView

按2个字段的总和和降序排序数据

聚合框架就是您想要的。不仅用于"聚合",还用于"操作"文档。因此,基本上,您希望$add运算符和$sort管道获得所需的结果。

我需要一些时间来启动Visual Studio,所以这里有一个不难翻译的外壳形式:

db.collection.aggregate([
    { "$project": {
        "item": 1,
        "category": 1,
        "mobileView": 1,
        "webView": 1,
        "totalView": { "$add": [ "$mobileView", "$webView" ] }
    }},
    { "$sort": { "totalView": -1 } }
])

因此,基本上"计算"一个字段,然后使用该"投影"结果作为$sort上的字段。

只是BSON文件,所以应该不会太难。

具体来说,对于C#语法,可以这样做:

var project = new BsonDocument {
    {
        "$project",
        new BsonDocument()
            .Add( "item", 1 )
            .Add( "category", 1 )
            .Add( "mobileView", 1 )
            .Add( 
                "totalView",
                new BsonDocument()
                    .Add( "$add", new BsonArray {
                        "$mobileView", "$webView"
                    })
            )
    } 
};
var sort = new BsonDocument {
    {
        "$sort",
        new BsonDocument {
            { "totalView", -1 }
        }
    }
};
var pipeline = new[] { project, sort };
var results = collection.Aggregate(pipeline);

所有$project项,与$group一样,都是要包含在阶段输出中的"显式"命名字段。在聚合框架中,您想要的字段是"要么全有要么全无",并且您必须指定您希望在下一个管道阶段或管道末端可见的每个字段。就管道而言,未提及的字段已不复存在。

想想unix风格的"管道"|,在这里你将一个命令的结果"链接"到另一个命令,这与这里发生的事情有着明显的相似之处。

我实际上写了一个Linq提供程序MongoLinqPlusPlus,用来生成像您这样的简单聚合框架管道。

因此,使用MongoLinqPlusPlus,您的查询就变成了:

collection.QueryablePlusPlus()
          .Select(c => new {
              OriginalDoc = c,
              SortKey = c.mobileView + c.webView
          })
          .OrderByDescending(c => c.SortKey)
          .Take(10)
          .Select(c => c.OriginalDoc)

(*如果我们能在排序(.OrderByDescending(c=>c.mobileView+c.webView)中进行算术运算,那就太好了,但聚合框架不直接支持这一点。因此,我选择要求开发人员显式地创建投影,而不是由Linq提供程序隐式地创建。)