如何在mongodb中选择嵌入文档中的所有项目?例如,我如何选择书中的所有项目?
{
"_id": 67
"Item_1":
{
"books": [
{"genre": "Classics", "author": "something"},
{"genre": "Fiction", "author": "something"}
{"genre": "Fiction", "author": "something"}
]¨
}
}
如果您希望稍微"平坦"一下您的模式,那么您可以使用聚合框架并使用 $project
管道操作符来做到这一点。这比.find()
提供的投影有更多的特性,在这个示例中,您还使用 $unwind
将数组"反规范化"为文档:
db.collection.aggregate([
{ "$unwind": "$Item_1.books" },
{ "$project": {
"genre": "$Item_1.books.genre", "author": "$Item_1.books.author"
}}
])
结果如下:
{ "_id": 67, "genre": "Classics", "author": "something" },
{ "_id": 67, "genre": "Fiction", "author": "something" }
{ "_id": 67, "genre": "Fiction", "author": "something" }
在那里保留一些引用原始文档的东西是有一定意义的,除非您将其排除在外,否则_id
将在那里。但如果你真的想要的话,你也可以排除。
另外,您可以针对多个结果筛选此列表,例如仅获得"小说"类型:
db.collection.aggregate([
{ "$unwind": "$Item_1.books" },
{ "$match": { "Item_1.books.genre": "Fiction" } }
{ "$project": {
"genre": "$Item_1.books.genre", "author": "$Item_1.books.author"
}}
])
给你:
{ "_id": 67, "genre": "Fiction", "author": "something" }
{ "_id": 67, "genre": "Fiction", "author": "something" }
对于多个文档,在管道中首先使用额外的 $match
也是有意义的,以减少在其数组中不包含"Fiction"类型的文档的数量。
MongoDB 2.6的另一种形式也可以这样做:
db.collection.aggregate([
{ "$match": { "Item_1.books.genre": "Fiction" } },
{ "$project": {
"books": {
"$setDifference: [
{ "$map": {
"input ": "$Item_1.books",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.genre", "Fiction" ] },
"$$el",
false
]
}
}},
[false]
]
}
}},
{ "$unwind": "$books" },
{ "$project": {
"genre": "$books.genre",
"author": "$books.fiction"
}}
])
这将数组元素上的 $match
移动到"内联"版本,以使用 $map
和 $setDifference
过滤数组的内容。这只是另一种方法,考虑到数组的大小,它的效用可能会有所不同,其中小的大小没有什么区别。
最后需要注意的是,您的模式似乎与作为对象的"Item_1"键分开了。如果您的实际意图是有许多这样的查询,并且确实在它们之间搜索或组合结果,那么模式更改将大大有利于您的查询:
{
"_id": 67
"books": [
{"type": "Item1", "genre": "Classics", "author": "something"},
{"type": "Item1", "genre": "Fiction", "author": "something"},
{"type": "Item1", "genre": "Fiction", "author": "something"},
{"type": "Item2", "genre": "Fiction", "author": "something"}
]¨
}
这样可以很容易地组合不同的键,或者实际上是分开或分组,而不必像现在那样直接指定到字段的路径。