获取 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"元素,这是基本投影做不到的。
我想使用聚合来仅使用那些在 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"元素,这是基本投影做不到的。