获取 mongodb 数组中的匹配元素

Get matching elements in mongodb array

我想使用聚合来仅使用那些在 2015-06-16 之后具有开始字段的门票来获取此数组。有人可以帮我处理管道吗?

{
    "name" : "array",
    "tickets" : [ 
        {
            "id" : 1,
            "sort" : true,
            "start" : ISODate("2015-06-15T22:00:00.000Z")
        },
        {
            "id" : 2,
            "sort" : true,
            "start" : ISODate("2015-06-16T22:00:00.000Z")
        },
        {
            "id" : 3,
            "sort" : true,
            "start" : ISODate("2015-06-17T22:00:00.000Z")
        }
    ]
}

您应该使用 Aggregation 来获取输出。

您应该使用以下查询:

db.collection.aggregate({
    $match: {
    name: "array"
    }
}, {
    $unwind: "$tickets"
}, {
    $match: {
    "tickets.start": {
        $gt: ISODate("2015-06-16")
    }
    }
}, {
    $group: {
    "_id": "name",
    "tickets": {
        $push: "$tickets"
    }
    }
})

的确,MongoDB 方法可用的 "standard projection" 操作,例如 .find() 只会 return 至多 "single matching element" 从数组到那个由 "projection" 部分中的 positional $ operator form in the "query" portion or the $elemMatch 查询。

为了执行这种 "ranged" 操作,您需要 aggregation framework,它在数组上具有更大的 "manipulation" 和 "filtering" 功能:

 collection.aggregate(
     array( 
         # First match the "document" to reduce the pipeline
         array(
             '$match' => array(
                 array( 
                    'tickets.start' => array(
                        '$gte' => new MongoDate(strtotime('2015-06-16 00:00:00'))
                    )
                )
             )
         ),

         # Then unwind the array
         array( '$unwind' => '$tickets' ),

         # Match again on the "unwound" elements to filter
         array(
             '$match' => array(
                 array( 
                    'tickets.start' => array(
                        '$gte' => new MongoDate(strtotime('2015-06-16 00:00:00'))
                    )
                )
             )
         ),

         # Group back to original structure per document
         array(
             '$group' => array( 
                  '_id' => '$_id',
                  'name' => array( '$first' => '$name' ),
                  'tickets' => array(
                      '$push' => '$tickets'
                  )
             )
         )           
     )
 ) 

或者您可以在输入时使用 $redact operator to simplify with MongoDB 2.6 or greater which basically uses the $cond 运算符语法:

 collection.aggregate(
     array( 
         # First match the "document" to reduce the pipeline
         array(
             '$match' => array(
                 array( 
                    'tickets.start' => array(
                        '$gte' => new MongoDate(strtotime('2015-06-16 00:00:00'))
                    )
                )
             )
         ),

         # Redact entries from the array
         array(
             '$redact' => array(
                 'if' => array(
                     '$gte' => array(
                         array( '$ifNull' => array(
                             '$start',
                             new MongoDate(strtotime('2015-06-16 00:00:00'))
                         )),
                         new MongoDate(strtotime('2015-06-16 00:00:00:00'))
                     )
                 ),
                 'then' => '$$DESCEND',
                 'else' => '$$PRUNE'
             )
         )
     )
 ) 

所以两个示例都在"filtering"中执行"same thing""do not"数组中满足指定条件的元素和return "more than one"元素,这是基本投影做不到的。