在 mongo 聚合中使用当前文档键

Posted

技术标签:

【中文标题】在 mongo 聚合中使用当前文档键【英文标题】:Use current document keys in mongo aggregate 【发布时间】:2019-11-30 05:17:26 【问题描述】:

我正在处理一个对我的订单进行排序的查询,为此我使用带有以下选项的 mongo 聚合。

$match
$lookup
$unwind
$sort
$skip
$limit

我的整个查询看起来像这样。

[
         "$match": query ,
        
            "$lookup": 
                "from": "orderstatuslogs",
                "localField": "_id",
                "foreignField": "orderId",
                "as": "filtered_statuses"
            
        ,
        
            "$lookup": 
                "from": "orderstatuslogs",
                "localField": "_id",
                "foreignField": "orderId",
                "as": "order_statuses"
            
        ,
        
            "$unwind": "$filtered_statuses"
        ,
        
            "$match": 
                'filtered_statuses.status': status
            
        ,
        
            "$sort":  'filtered_statuses.createdAt': sort 
        ,
         '$skip': skip ,
         "$limit": limit ,
    ]

我目前面临的问题是第二个$match'filtered_statuses.status': status。 匹配状态应该来自当前文档,类似于$order_status,我们在每个文档中都有名为order_status 的密钥,我想使用该密钥进行匹配,但我不明白如何使用该密钥。

我的整个文档看起来像这样。


    "_id" : ObjectId("5d3496e9bf9c0a1b0a4bbdd1"),
    "products" : [ 
        ObjectId("5d3496e9bf9c0a1b0a4bbdd0")
    ],
    "isGiftCard" : true,
    "order_status" : "NEW",
    "total_price" : 240,
    "discount" : 0,
    "isConcierge" : false,
    "note" : "",
    "time" : "2019-05-12T10:28:43.316Z",
    "userId" : ObjectId("5cfcaf6d249ff4a6340d9385"),
    "trackId" : "891383",
    "isPackaged" : false,
    "sender_details" : ObjectId("5cfcaf6d249ff4a6340d9385"),
    "timeSlot" : ObjectId("5cfcfc2e2ae5a0e3d43af363"),
    "createdAt" : ISODate("2019-07-21T16:46:33.859Z"),
    "updatedAt" : ISODate("2019-07-21T17:26:34.243Z"),
    "__v" : 0,
    "recipient" : ObjectId("5cfcfbf32ae5a0e3d43af35e"),
    "recipient_details" : ObjectId("5d349cc5a8f5cf1d345934d8"),
    "delivery_method" : ObjectId("5cfcfbb32ae5a0e3d43af35a"),
    "gift_card" : ObjectId("5d0107009786972878fcf811"),
    "gift_card_text" : "Eid Ma***",
    "payment" : ObjectId("5d349cc8a8f5cf1d345934d9"),
    "payment_type" : ObjectId("5cfcfb802ae5a0e3d43af358"),
    "filtered_statuses" : 
        "_id" : ObjectId("5d349cd5a8f5cf1d345934da"),
        "status" : "NEW",
        "active" : true,
        "userId" : ObjectId("5cfcaf6d249ff4a6340d9385"),
        "orderId" : ObjectId("5d3496e9bf9c0a1b0a4bbdd1"),
        "createdAt" : ISODate("2019-07-21T17:11:49.796Z"),
        "updatedAt" : ISODate("2019-07-21T17:11:49.796Z"),
        "__v" : 0
    ,
    "order_statuses" : [ 
        
            "_id" : ObjectId("5d349cd5a8f5cf1d345934da"),
            "status" : "NEW",
            "active" : true,
            "userId" : ObjectId("5cfcaf6d249ff4a6340d9385"),
            "orderId" : ObjectId("5d3496e9bf9c0a1b0a4bbdd1"),
            "createdAt" : ISODate("2019-07-21T17:11:49.796Z"),
            "updatedAt" : ISODate("2019-07-21T17:11:49.796Z"),
            "__v" : 0
        
    ]

正如您在我当前的文档中看到的那样,我有 order_status,我想在 $match 查询中使用相同的键来过滤我的某些结果。

有人可以帮我吗?

我已经搜索了很多,但没有找到正确的方法。

提前谢谢大家。

【问题讨论】:

【参考方案1】:

首先,您应该在$lookup 阶段使用let 键来创建可以引用到$match 阶段的变量。

其次,你应该在$lookuppipeline键中使用$match阶段:

        
            "$lookup": 
                "from": "orderstatuslogs",
                "let":  order_status: "$order_status" , // $order_status will refer to the order_status field in the main document
                "localField": "_id",
                "foreignField": "orderId",
                "as": "filtered_statuses",
                "pipeline": 
                    "$match": 
                        $expr:  $eq: [ "$status", "$$order_status" ] 
                    
                
            
        ,

最后,您可以删除第二个 $match 阶段,因为它不再需要了。

【讨论】:

以上是关于在 mongo 聚合中使用当前文档键的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 mongo 聚合循环遍历数组并返回所需的文档?

mongoDB应用篇-mongo聚合查询

mongo中的高级查询之聚合操作(distinct,count,group)与数据去重

Mongo 聚合计数子文档(计数回复评论)

如何使用 mongo 聚合将字符串转换为日期?

为啥聚合+排序比mongo中的查找+排序更快?