Return 存在给定字段的数组子集
Return a subset of array where a given field is present
我想过滤 Categories
嵌入式数组以仅获取具有 parent
键的数组。
{
"_id": ObjectId("5737283639533c000978ae71"),
"name": "Swiss",
"Categories": [
{
"name": "Management",
"_id": ObjectId("5738982e39533c00070f6a53")
},
{
"name": "Relations",
"_id": ObjectId("5738984a39533c000978ae72"),
"parent": ObjectId("5738982e39533c00070f6a53")
},
{
"name": "Ambiance",
"_id": ObjectId("57389bed39533c000b148164")
}
]
}
我试过 find
但没有成功。
经过一些研究,它似乎可以通过聚合命令完成,但我不喜欢它的工作方式,我更愿意只使用 find 命令。
此外,我问自己,就性能而言,将每个类别存储在一个新集合中是否更好,是吗?
编辑,我想得到这样的东西作为查找输出:
[
{
"name": "Relations",
"_id": ObjectId("5738984a39533c000978ae72"),
"parent": ObjectId("5738982e39533c00070f6a53")
}
]
作为根据上述描述的解决方案,请尝试执行以下查询
db.mycoll.find({Categories:{$elemMatch:{parent:{$exists:true}}}},
{Categories:{$elemMatch:{parent:{$exists:true}}}})
以上示例使用 $elemMatch 运算符过滤嵌入文档中的元素。
最佳方法是在 MongoDB 3.2 中使用聚合框架。您所需要的只是投影您的文档并在 cond
表达式中使用 $filter
operator to return a subset of the "Categories" array that match your criteria, but to do this you will need to use $ifNull
operator give a "default" value to the "parent" field in all those sub-documents where that field is missing then use the $ne
来确定给定元素应包含在子集中的何处。
db.collection.aggregate([
{ "$project" : {
"_id": 0,
"Categories": {
"$filter": {
"input": "$Categories",
"as": "catg",
"cond": {
"$ne": [
{ "$ifNull": [ "$$catg.parent", false ] },
false
]
}
}
}
}}
])
从 3.0 版开始,您需要一种不同的方法。相反,您需要使用 $map
operator to return a give element if it matches your criteria or false
then use the $setDifference
运算符来过滤掉返回数组中等于 false
的所有元素。当然 $setDifference
只要被过滤的数据是“唯一的”就可以了。
db.collection.aggregate([
{ "$project" : {
"_id": 0,
"Categories": {
"$setDifference": [
{ "$map": {
"input": "$Categories",
"as": "catg",
"in": {
"$cond": [
{ "$ne": [
{ "$ifNull": [ "$$catg.parent", false ] },
false
]},
"$$catg",
false
]}
}
},
[ false ]
]
}
}}
])
PHP 中的翻译给出:
db.collection.aggregate(
array(
array("$project" => array(
"_id" => 0,
"Categories" => array(
"$filter" => array(
"input" => "$Categories",
"as" => "catg",
"cond" => array(
"$ne" => array(
array("$ifNull" => array("$$catg.parent", false),
false
)
)
)
)
))
)
)
还有这个:
db.collection.aggregate(
array(
array("$project" => array(
"_id" => 0,
"Categories" => array(
"$setDifference" => array(
"$map" => array(
"input" => "$Categories",
"as" => "catg",
"in" => array(
"$cond" => array(
"$ne" => array(
array("$ifNull" => array( "$$catg.parent", false ) ),
false
),
"$$catg",
false
)
),
array(false)
)
)
))
)
)
我想过滤 Categories
嵌入式数组以仅获取具有 parent
键的数组。
{
"_id": ObjectId("5737283639533c000978ae71"),
"name": "Swiss",
"Categories": [
{
"name": "Management",
"_id": ObjectId("5738982e39533c00070f6a53")
},
{
"name": "Relations",
"_id": ObjectId("5738984a39533c000978ae72"),
"parent": ObjectId("5738982e39533c00070f6a53")
},
{
"name": "Ambiance",
"_id": ObjectId("57389bed39533c000b148164")
}
]
}
我试过 find
但没有成功。
经过一些研究,它似乎可以通过聚合命令完成,但我不喜欢它的工作方式,我更愿意只使用 find 命令。
此外,我问自己,就性能而言,将每个类别存储在一个新集合中是否更好,是吗?
编辑,我想得到这样的东西作为查找输出:
[
{
"name": "Relations",
"_id": ObjectId("5738984a39533c000978ae72"),
"parent": ObjectId("5738982e39533c00070f6a53")
}
]
作为根据上述描述的解决方案,请尝试执行以下查询
db.mycoll.find({Categories:{$elemMatch:{parent:{$exists:true}}}},
{Categories:{$elemMatch:{parent:{$exists:true}}}})
以上示例使用 $elemMatch 运算符过滤嵌入文档中的元素。
最佳方法是在 MongoDB 3.2 中使用聚合框架。您所需要的只是投影您的文档并在 cond
表达式中使用 $filter
operator to return a subset of the "Categories" array that match your criteria, but to do this you will need to use $ifNull
operator give a "default" value to the "parent" field in all those sub-documents where that field is missing then use the $ne
来确定给定元素应包含在子集中的何处。
db.collection.aggregate([
{ "$project" : {
"_id": 0,
"Categories": {
"$filter": {
"input": "$Categories",
"as": "catg",
"cond": {
"$ne": [
{ "$ifNull": [ "$$catg.parent", false ] },
false
]
}
}
}
}}
])
从 3.0 版开始,您需要一种不同的方法。相反,您需要使用 $map
operator to return a give element if it matches your criteria or false
then use the $setDifference
运算符来过滤掉返回数组中等于 false
的所有元素。当然 $setDifference
只要被过滤的数据是“唯一的”就可以了。
db.collection.aggregate([
{ "$project" : {
"_id": 0,
"Categories": {
"$setDifference": [
{ "$map": {
"input": "$Categories",
"as": "catg",
"in": {
"$cond": [
{ "$ne": [
{ "$ifNull": [ "$$catg.parent", false ] },
false
]},
"$$catg",
false
]}
}
},
[ false ]
]
}
}}
])
PHP 中的翻译给出:
db.collection.aggregate(
array(
array("$project" => array(
"_id" => 0,
"Categories" => array(
"$filter" => array(
"input" => "$Categories",
"as" => "catg",
"cond" => array(
"$ne" => array(
array("$ifNull" => array("$$catg.parent", false),
false
)
)
)
)
))
)
)
还有这个:
db.collection.aggregate(
array(
array("$project" => array(
"_id" => 0,
"Categories" => array(
"$setDifference" => array(
"$map" => array(
"input" => "$Categories",
"as" => "catg",
"in" => array(
"$cond" => array(
"$ne" => array(
array("$ifNull" => array( "$$catg.parent", false ) ),
false
),
"$$catg",
false
)
),
array(false)
)
)
))
)
)