当前位置: 首页 > 面试题库 >

在MongoDB中计算的分组依据字段

孟花蜂
2023-03-14
问题内容

对于MongoDB文档中的示例,如何使用MongoTemplate编写查询?

db.sales.aggregate(
   [
      {
        $group : {
           _id : { month: { $month: "$date" }, day: { $dayOfMonth: "$date" }, year: { $year: "$date" } },
           totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } },
           averageQuantity: { $avg: "$quantity" },
           count: { $sum: 1 }
        }
      }
   ]
)

或一般来说,如何按计算字段分组?


问题答案:

实际上,您可以先使用“项目”来做类似的事情,但是对我来说, $project 事先需要一个阶段有点反常理:

    Aggregation agg = newAggregation(
        project("quantity")
            .andExpression("dayOfMonth(date)").as("day")
            .andExpression("month(date)").as("month")
            .andExpression("year(date)").as("year")
            .andExpression("price * quantity").as("totalAmount"),
        group(fields().and("day").and("month").and("year"))
            .avg("quantity").as("averavgeQuantity")
            .sum("totalAmount").as("totalAmount")
            .count().as("count")
    );

就像我说的那样,违反直觉,因为您应该只可以在 $group
舞台上声明所有这些内容,但是助手似乎并没有这样工作。序列化有点有趣(用数组包装date运算符参数),但是它确实起作用了。但是,这是两个流水线阶段,而不是一个。

这是什么问题?通过将阶段分开,“项目”部分会强制处理管道中的所有文档,以便获得计算出的字段,这意味着在进入分组阶段之前,它会经过所有步骤。

通过以两种形式运行查询,可以清楚地看到处理时间的差异。在一个单独的项目阶段,在我的硬件上执行该查询所需的时间比在“组”操作期间计算所有字段的查询要长三倍。

因此,似乎目前唯一正确构建此方法的方法是自己构建管道对象

    ApplicationContext ctx =
            new AnnotationConfigApplicationContext(SpringMongoConfig.class);
    MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");

    BasicDBList pipeline = new BasicDBList();
    String[] multiplier = { "$price", "$quantity" };

    pipeline.add(
        new BasicDBObject("$group",
            new BasicDBObject("_id",
                new BasicDBObject("month", new BasicDBObject("$month", "$date"))
                    .append("day", new BasicDBObject("$dayOfMonth", "$date"))
                    .append("year", new BasicDBObject("$year", "$date"))
            )
            .append("totalPrice", new BasicDBObject(
                "$sum", new BasicDBObject(
                    "$multiply", multiplier
                )
            ))
            .append("averageQuantity", new BasicDBObject("$avg", "$quantity"))
            .append("count",new BasicDBObject("$sum",1))
        )
    );

    BasicDBObject aggregation = new BasicDBObject("aggregate","collection")
        .append("pipeline",pipeline);

    System.out.println(aggregation);

    CommandResult commandResult = mongoOperation.executeCommand(aggregation);

或者,如果所有这些看起来都很麻烦,那么您始终可以使用JSON源进行解析。但是,当然,它必须是有效的JSON:

    String json = "[" +
        "{ \"$group\": { "+
            "\"_id\": { " +
                "\"month\": { \"$month\": \"$date\" }, " +
                "\"day\": { \"$dayOfMonth\":\"$date\" }, " +
                "\"year\": { \"$year\": \"$date\" } " +
            "}, " +
            "\"totalPrice\": { \"$sum\": { \"$multiply\": [ \"$price\", \"$quantity\" ] } }, " +
            "\"averageQuantity\": { \"$avg\": \"$quantity\" }, " +
            "\"count\": { \"$sum\": 1 } " +
        "}}" +
    "]";

    BasicDBList pipeline = (BasicDBList)com.mongodb.util.JSON.parse(json);


 类似资料:
  • 问题内容: 我有如下的SQL: 并得到结果: 我想总结每个部门的学生人数,如下所示: 我该如何编写sql? 问题答案: 尽管您似乎并未显示所有表格,但我只能假设还有每位学生的实际入学表格 如果您想要与每个学生相关联的每个部门的总数(这没有意义),则可能必须这样做… 我对“姓名”列的解释是学生的姓名,而不是班级实际讲师的姓名,因此,我进行子选择/加入。否则,就像其他人一样,只需要使用COUNT(*)

  • 问题内容: 我的mysql数据库中有一个表,该表有两列:组和子组。见下文。 我正在尝试获取每个唯一的夫妇组/子组的记录数。 这是我期望的: 阅读一些帖子后,我尝试使用count()的group by尝试了几个sql查询,但是我无法获得预期的结果。我怎样才能解决这个问题? 问题答案: 我认为您正在寻找:

  • 问题内容: 我有一个看起来像这样的模型: 我想要为每个类别选择项目的计数(只是计数),因此在SQL中,它会像这样简单: 有没有相当于做这种“ Django方式”?还是纯SQL是唯一的选择?我熟悉Django中的count()方法,但是我看不出group by如何适合那里。 问题答案: 正如我刚刚发现的,这里是如何使用Django 1.1聚合API进行此操作:

  • 问题内容: 我正在尝试转换此查询(已经可以使用) 对于Linq to SQL,但我不知道自己在做什么错。看我的尝试 我只需要对建筑物进行分组并计算每个建筑物有多少用户。 问题答案: 只需使用以下方法:

  • 问题内容: 我需要在ES中使用3个字段进行汇总(分组)。 我可以在1个查询中执行此操作,还是需要对每列使用facet +迭代? 谢谢 问题答案: 您可以通过2种方式来做到这一点: 1)在一个方面中使用多个字段: 单个字段facet的示例: 单面结果中多个字段的示例: 2)使用多方面结果集: 参考链接:http : //www.elasticsearch.org/guide/reference/ap

  • 问题内容: 我希望能够从电子邮件表中选择一堆行并按发件人分组。我的查询如下所示: 该查询几乎可以按我希望的方式工作-它选择按电子邮件分组的记录。问题在于主题和时间戳记与特定电子邮件地址的最新记录不符。 例如,它可能返回: 当数据库中的记录是: 如果“编程问题”主题是最新的,那么在对电子邮件进行分组时如何使MySQL选择该记录? 问题答案: 一个简单的解决方案是将查询包裹与ORDER语句子选择 第一