如何在MongoDB中使用$ slice $ filter结果?

时间:2018-02-14 16:40:10

标签: mongodb mongodb-query aggregation-framework

我有一个具有以下格式的项目集合:

{
    "_id": 123,
    "items": [{
        "name": "item1",
        "status" : "inactive",
        "created" : ISODate("2018-02-14T10:39:28.321Z")
    },
    {
        "name": "item2",
        "status" : "active",
        "created" : ISODate("2018-02-14T10:39:28.321Z")
    },
    {
        "name": "item3",
        "status" : "active",
        "created" : ISODate("2018-02-14T10:39:28.321Z")
    },
    {
        "name": "item4",
        "status" : "inactive",
        "created" : ISODate("2018-02-14T10:39:28.321Z")
    },
    {
        "name": "item5",
        "status" : "active",
        "created" : ISODate("2018-02-14T10:39:28.321Z")
    }
    ]
}

我想查询商品的状态字段,以便状态为'有效的对象'仅在数组中返回,并且还跳过最后1,并在查询中返回限制2。

目前我使用$ filter(聚合)进行此操作,通过使用以下查询,它只返回最后一条记录:

db.item.aggregate([
    { "$match": { "items.status": "active" } }, 
    { "$project": { 
        "items": { 
            "$slice": [ 
                { "$filter": { 
                    "input": "$items",
                    "as": "item", 
                    "cond": { "$eq": [ "$$item.status", "active" ] } 
                }}, 
                -1,2 
            ] 
        } 
    }}
])

输出应为:

{
    "_id": 123,
    "items": [
{
        "name": "item2",
        "status" : "active",
        "created" : ISODate("2018-02-14T10:39:28.321Z")
    },
    {
        "name": "item3",
        "status" : "active",
        "created" : ISODate("2018-02-14T10:39:28.321Z")
    }]
}

请帮我实现这个结果。

1 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是这样的(根据您的数据结构以及您可能仍希望保留它的索引设置,不需要$ match阶段,但出于性能原因):

 db.item.aggregate([
    { "$project": { 
        "items": { 
            "$slice": [ 
                { "$filter": { 
                    "input": "$items",
                    "as": "item", 
                    "cond": { "$eq": [ "$$item.status", "active" ] } 
                }}, 
                -3,2 
            ] 
        } 
    }}
])

我认为使用以下查询可能会更好:

db.items.db.aggregate([
{
    $project: {
        "items": {
            "$filter": { 
                "input": "$items",
                "as": "item", 
                "cond": { "$eq": [ "$$item.status", "active" ] } 
            }
        } 
    }
}, {
    $project: {
        "items": {
            $slice: [
                {
                    $slice: [
                        "$items",
                        {
                            $subtract: [ { $size: "$items" }, 1 ] // length of items array minus one
                        } 
                    ]
                }, 2 // max two elements
            ]
        }
    }
}])

因为这个将首先摆脱最后一个元素然后将输出限制为两个项目,这可能是你想要的小于3"活跃"元件。