检索与数组中的最大值匹配的子文档

时间:2016-06-02 14:25:54

标签: node.js mongodb mongodb-query aggregation-framework

我在mongodb中有以下数据结构

[
    {
        "id" : "unique id 1",
        "timeStamp" : "timeStamp",
        "topicInfo" : [
            { 
                topic : "topic1", 
                offset : "offset number",
                time: 1464875267637
            },
            { 
                topic : "topic2", 
                offset : "offset number",
                time: 1464875269709
            },
            { 
                topic : "topic3", 
                offset : "offset number",
                time : 1464875270849
            }
       ]
   },
   {
       "id" : "unique id 2",
       "timeStamp" : "timeStamp",
       "topicInfo" : [
           { 
               topic : "15", 
               offset : "offset number",
               time : 1464875271884
           },
           { 
               topic : "topic2", 
               offset : "offset number",
               time : 1464875273887
           },
           { 
               topic : "topic3", 
               offset : "offset number",
               time : 1464875272848
           }
       ]
   }
 ]

现在我想找到所有名为“topic2”的主题条目,并且时间值与“topicInfo”数组中的其他对象相比最大。我也想用“timeStamp”对它们进行排序。从示例代码中,查询应返回第二个对象。我无法编写查询任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

执行此操作的最佳方法是MongoDB 3.2或更高版本。我们需要$project我们的文档并使用$filter运算符返回与我们的条件匹配的“topicInfo”数组的子集。从MongoDB3.2开始,我们可以在$project ition表达式的cond阶段使用$max,并对返回的值执行逻辑运算。

管道中的最后一个阶段是$match阶段,您可以使用$exists元素查询运算符和dot notation过滤掉那些带有空“topicInfo”的文档来访问第一个元素在数组中。这也减少了通过线路发送的数据量以及用于解码客户端文档的时间和内存。

db.collection.aggregate([
    { "$project": { 
        "topicInfo": { 
            "$filter": { 
                "input": "$topicInfo", 
                "as": "t", 
                "cond": { 
                    "$and": [ 
                        { "$eq": [ "$$t.topic", "topic2"] }, 
                        { "$eq": [ "$$t.time", { "$max": "$topicInfo.time" } ] }
                    ] 
                } 
            } 
        } 
    }},
    { "$match": { "topicInfo.0": { "$exists": true } } }
])

答案 1 :(得分:1)

您可以使用这样的聚合框架:

db.test.aggregate(
    { $unwind: '$topicInfo' }, 
    { $match: { 'topicInfo.topic': 'topic2' } }, 
    { $group: { 
        _id: '$id', 
        timestamp: { $first: '$timestamp' }, 
        time: { $max: '$topicInfo.time' } } 
     }, 
     { $sort: { timestamp: 1 } }).pretty()