从子文档的数组中查找数据时使用$ slice

时间:2016-06-07 20:02:41

标签: mongodb mongodb-query aggregation-framework

我需要从“_id”定义的文档中获取子文档数组中的最新条目。

该文件如下:

{
"_id": "nex67",
"ownedparts": [
    {
        "id": "tool1",
        "history": [
            {
                "time": ISODate("2016-06-07T09:12:54.015Z"),
                "value": 300
            },
            {
                "time": ISODate("2016-06-07T09:12:54.015Z"),
                "value": 240
            }
        ]
    },
    {
        "id": "screw1",
        "history": [
            {
                "time": ISODate("2016-06-07T09:12:54.015Z"),
                "value": 500
            }
        ]
    }
]}

通过此查询,我获得了“tool1”的完整历史记录:

db.users.find(  
{
    "_id": "nex67",
    "ownedparts.id": "tool1"
},  { "ownedparts.history.$": 1 })

使用此命令我得到最新的条目,但它从“tool1”和“screw1”返回它们:

db.users.find(  
{"_id": "nex67"},
{"ownedparts.history": { $slice: -1 }})

所以基本上我需要帮助组合这些查询,以便我可以从nex67的工具1获取最新的历史记录条目。

我需要的结果应该是这样的:

{
    "_id" : "nex67",
    "ownedparts" : [
            {
                    "id" : "tool1",
                    "history" : [
                            {
                                    "time" : ISODate("2016-06-07T09:12:54.015Z"),
                                    "value" : 240
                            }
                    ]
            }
    ]}

3 个答案:

答案 0 :(得分:2)

执行此操作的最佳方法是使用$arrayElemAt$filter运算符在MongoDB 3.2中。

db.users.aggregate(
    [
        { "$match": { "_id": "nex67", "ownedparts.id": "tool1" } }, 
        { "$project": { 
            "ownedparts": { 
                "$let": { 
                    "vars": { 
                        "el": { 
                            "$arrayElemAt": [ 
                                { "$filter": { 
                                    "input": "$ownedparts", 
                                    "as": "own", 
                                    "cond": { "$eq": [ "$$own.id", "tool1" ] }
                                }}, 
                                0 
                            ]
                        }
                    }, 
                    "in": { 
                        "id": "$$el.id", 
                        "history": { "$arrayElemAt": [ "$$el.history", -1 ] } 
                    }
                }
            }
        }}
    ]
)

产生:

{ 
    "_id" : "nex67", 
    "ownedparts" : { 
        "id" : "tool1", 
        "history" : {
            "time" : ISODate("2016-06-07T09:12:54.015Z"), 
            "value" : 240 
        } 
    }
}

答案 1 :(得分:1)

由于我们有嵌套数组 - 这不是一个小问题。 为了解决这个问题,我们需要使用聚合框架,选择第一个记录project,然后选择unwind数组来减少嵌套,最后project2根据需要重建文档。 match用作过滤器来重新生成正在处理的文档数量。

var match = {
    $match : {
        "_id" : "nex67"
    }
}

var project = {
    $project : {
        _id : 1,
        ownedpartsFirst : {
            $slice : ["$ownedparts", 1]
        }
    }
}
var unwind = {
    $unwind : "$ownedpartsFirst"
}
var project2 = {
    $project : {
        _id : 1,
        ownedparts :
        [{
                id : "$ownedpartsFirst.id",
                history : {
                    $slice : ["$ownedpartsFirst.history", -1]
                }
            }
        ]
    }
}

db.collectionName.aggregate([match, project, unwind, project2])
  

输出:

{
    "_id" : "nex67",
    "ownedparts" : [ 
        {
            "id" : "tool1",
            "history" : [ 
                {
                    "time" : ISODate("2016-06-07T09:12:54.015Z"),
                    "value" : 240.0
                }
            ]
        }
    ]
}

答案 2 :(得分:-1)

试试这个

db.users.find(  
         {"_id": "nex67"},
         {"ownedparts.$.history": { $slice: -1 }})

你有这个咨询的问题

 db.users.find(  
{
         "_id": "nex67",
         "ownedparts.id": "tool1"
},  { "ownedparts.history.$": 1 })

simbol $介于ownparts和history之间,以从你的数组中获取元素

 db.users.find(  
{
         "_id": "nex67",
         "ownedparts.id": "tool1"
},  { "ownedparts.$.history": 1 })