【问题标题】:filter and sort subdocuments by Date with Mongo / Mongoose使用 Mongo / Mongoose 按日期过滤和排序子文档
【发布时间】:2019-10-09 15:40:50
【问题描述】:

我有一个像下面这样的 Mongoose 模型。我想要一些子文档排序,并按日期过滤(例如,只有最后 10 个子文档)

TotalPlafond 有一个编号 (tot_plafond),以及每个债务人的子 Plafond 列表。 tot_plafond 更新计算 debtor_plafond 的列表,该列表是对所有传输进行求和计算的。 当我询问 TotalPlafond 时,我只想要最后 10 次转账,所以我应该按日期订购转账,然后只取最后 10 次。 我也可能需要在两个日期之间进行一些转移。

我怎么能用猫鼬做到这一点?

这显然行不通。

// this just orders resulting docs, not subdocs
TotalPlafond.findById(id)
            .sort('debtor_plafonds.debtor_taks.transfers.date')

这是我的模特:

/* ====  TotalPlafond Mongoose Model ==== */
{
 tot_plafond     : {type : Number},
 debtor_plafonds : [
    {
       debtor_id      : {type: ObjectID},
       debtor_plafond : {type : Number},
       debtor_taks: [
          {
            task_id   : {type : ObjectID},
            transfers : [ 
                         {
                          amount : {type : Number},
                          date   : {type : Date}
                         }
                        ]
          }
       ]
    }
 ]
}

我想使用一个 TotalPlafond(例如TotalPlafond.findById(id)),其中包含所有的债务人平台,但每个债务人平台的每个债务人任务只有最后 10 次转移

【问题讨论】:

  • 我不清楚传输数组,因为它必须是一个带有“金额”和“日期”键的对象数组。
  • 抱歉,缺少括号。现在已经修复了
  • 您要获取每个“debtor_plafonds”的最后 10 次“转账”吗?
  • 能否请您添加示例文档和您想要的结果(如果可能)。写一个查询会很有帮助。
  • 是的,我想使用一个 TotalPlafond(例如TotalPlafond.findById(id)),其中包含所有的 debtor_plafond,但每个 debor_plafond 的每个 debor_task 的最后 10 次转移

标签: mongodb mongoose mongodb-query


【解决方案1】:

你可以试试下面的:

db.collection.aggregate([
    {
        $match: {
            _id: ObjectId("5ce66416ff87476e5eef0398")
        }        
    },
    {
        $unwind: "$debtor_plafonds"
    },
    {
        $unwind: "$debtor_plafonds.debtor_taks"
    },
    {
        $unwind: "$debtor_plafonds.debtor_taks.transfers"
    },
    {
        $sort: { 
            "debtor_plafonds.debtor_taks.transfers.date": -1
        }
    },
    {
        $group: {
            _id: {
                "_id": "$_id",  
                "tot_plafond": "$tot_plafond",  
                "debtor_plafonds": "$debtor_plafonds.debtor_id",
                "debtor_taks": "$debtor_plafonds.debtor_taks.task_id",
            },
            // data : { $push: "$$ROOT" },
            transfers : { 
                $push: { 
                    "amount": "$debtor_plafonds.debtor_taks.transfers.amount",
                    "date": "$debtor_plafonds.debtor_taks.transfers.date"    
                } 
            }
        }
    },
    {
        $project: {
            _id: "$_id._id",
            tot_plafond: "$_id.tot_plafond",
            debtor_plafonds: "$_id.debtor_plafonds",
            debtor_taks: "$_id.debtor_taks",
            transfers: { $slice : [ "$transfers",2 ] }
        }
    }
])

我试过它将虚拟数据。你会得到如下结果:

/* 1 createdAt:23/05/2019, 14:42:54*/
{
    "_id" : ObjectId("5ce66416ff87476e5eef0398"),
    "tot_plafond" : 20,
    "debtor_plafonds" : ObjectId("5c8d5cd4d8d2ab15b37c780a"),
    "debtor_taks" : ObjectId("5cad84b93d124a151f633af1"),
    "transfers" : [
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        },
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        }
    ]
},

/* 2 createdAt:23/05/2019, 14:42:54*/
{
    "_id" : ObjectId("5ce66416ff87476e5eef0398"),
    "tot_plafond" : 20,
    "debtor_plafonds" : ObjectId("5c8d5cd4d8d2ab15b37c780a"),
    "debtor_taks" : ObjectId("5c91c0f121a78f19d9eb3531"),
    "transfers" : [
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        },
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        }
    ]
},

/* 3 createdAt:23/05/2019, 14:42:54*/
{
    "_id" : ObjectId("5ce66416ff87476e5eef0398"),
    "tot_plafond" : 20,
    "debtor_plafonds" : ObjectId("5ca449f6b3171315a29a90dc"),
    "debtor_taks" : ObjectId("5ca449f6b3171315a29a90db"),
    "transfers" : [
        {
            "amount" : 10,
            "date" : ISODate("2019-02-20T10:32:00.313+05:30")
        },
        {
            "amount" : 10,
            "date" : ISODate("2019-02-19T10:32:00.313+05:30")
        }
    ]
},

/* 4 createdAt:23/05/2019, 14:42:54*/
{
    "_id" : ObjectId("5ce66416ff87476e5eef0398"),
    "tot_plafond" : 20,
    "debtor_plafonds" : ObjectId("5cad84b93d124a151f633af0"),
    "debtor_taks" : ObjectId("5cad84b93d124a151f633af2"),
    "transfers" : [
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        },
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        }
    ]
},

/* 5 createdAt:23/05/2019, 14:42:54*/
{
    "_id" : ObjectId("5ce66416ff87476e5eef0398"),
    "tot_plafond" : 20,
    "debtor_plafonds" : ObjectId("5ca449f6b3171315a29a90dc"),
    "debtor_taks" : ObjectId("5cad84b93d124a151f633af3"),
    "transfers" : [
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        },
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        }
    ]
},

/* 6 createdAt:23/05/2019, 14:42:54*/
{
    "_id" : ObjectId("5ce66416ff87476e5eef0398"),
    "tot_plafond" : 20,
    "debtor_plafonds" : ObjectId("5cad84b93d124a151f633af0"),
    "debtor_taks" : ObjectId("5c91c0f121a78f19d9eb3532"),
    "transfers" : [
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        },
        {
            "amount" : 10,
            "date" : ISODate("2019-02-18T10:32:00.313+05:30")
        }
    ]
}

让我知道你想要的结果,我会为此修改查询。

【讨论】:

  • 您好,谢谢您,我正在测试它。无论如何,这只是为了排序,对吗?没有“过滤器”,例如最近 10 次转账,或 2 个日期之间的所有转账
  • 实际上,我可以将排序过程委托给客户端,避免服务器过载。但是查询应该只过滤我需要的转账(过去 10 天或两个日期之间)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
  • 2019-07-13
  • 1970-01-01
  • 2019-11-28
  • 2017-10-07
  • 2013-04-18
  • 2017-10-07
相关资源
最近更新 更多