MongoDB聚合查询 - 返回嵌套子文档中的所有项目
Posted
技术标签:
【中文标题】MongoDB聚合查询 - 返回嵌套子文档中的所有项目【英文标题】:MongoDB aggregation query - return all items inside nested subdocument 【发布时间】:2021-07-27 08:26:50 【问题描述】:基本上,我有一个嵌套的对象数组。我想从这些对象中提取信息,并将所有结果作为数组返回。
这是我的数据:
[
"_id": "608642db80a36336946620aa",
"title": "titleHere",
"types":
"flashcardReversed": [
"normal": // the data inside of "normal" should become its own object in the returned array
"_id": "608d5b290e635ece6828141X",
"front": "2front",
"back": "2back"
,
"reversed": // the data inside of "reversed" should become its own object in the returned array
"_id": "608t5b290e635ece6828141Y",
"front": "2frontReversed",
"back": "2backReversed"
,
"normal":
"_id": "608a5b31a3f9806de253726X",
"front": "2front2",
"back": "2back2"
,
"reversed":
"_id": "608a5b31a3f9806de253726Y",
"front": "2frontReversed2",
"back": "2backReversed2"
]
]
这是想要的结果:
[
"flashcardReversed": [
"_id": "608d5b290e635ece6828141X",
"front": "2front",
"back": "2back"
,
"_id": "608t5b290e635ece6828141Y",
"front": "2frontReversed",
"back": "2backReversed"
,
"_id": "608t5b290e635ece6828141Y",
"front": "2frontReversed",
"back": "2backReversed"
,
"_id": "608a5b31a3f9806de253726Y",
"front": "2frontReversed2",
"back": "2backReversed2"
]
]
我目前的尝试:https://mongoplayground.net/p/k3Fjd59KMKg
我曾尝试通过各种方法合并$card
和$card2
文档,然后使用$replaceRoot
来创建所需的结果 - 但经过长时间的尝试,我没有成功。
关于我的用例的一些说明 -
我将在$facet
中使用这个管道
flashcardReversed
内部会有很多对象,都是从同一个 Mongoose Schema 创建的
文档最多应包含 ~2000 张卡片。我需要在反应网站中使用的结果。我应该担心这个搜索的效率吗? (如果这本身就是一个问题,我很乐意将其移动)。
如果我的 Mongoose Schema 有帮助,请告诉我,我可以添加它们。
感谢所有帮助,
- Riley Swinson
【问题讨论】:
原版中是否总是“正常”和“反转”键?还是可以有更多? @CodyG 可以有很多文档,都具有相同的结构。我会澄清我的帖子。谢谢! 【参考方案1】:我能够想出这个查询来得到想要的结果
db.collection.aggregate([
"$unwind": "$types.flashcardReversed"
,
"$project":
"flashcardReversed":
"$map":
"input":
"$objectToArray": "$types.flashcardReversed"
,
"as": "elem",
"in": "$$elem.v"
,
"$unwind": "$flashcardReversed"
,
"$group":
"_id": 1,
"flashcardReversed":
"$push": "$flashcardReversed"
,
"$project":
"_id": 0
])
上述管道的解释:
-
使用
$unwind
将数组划分为其元素
使用$project
和$map
将flashcardReversed
对象转换为值数组。使用$map
允许管道处理正常和反转之上的任何其他键
使用$unwind
再次拆分步骤2中形成的flashcardReversed数组
使用 $group
和 $push
累加器将 flashcardReversed
的所有值添加到单个数组中
使用$project
从响应中删除_id
字段
这是一个 Mongodb 游乐场link 相同
【讨论】:
【参考方案2】:这可以通过
$unwind 拆分闪存卡阵列 $project 将包含 normal/reverse 的对象转换为数组 $unwind 创建的数组 $group by _id 并收集数组中的值db.collection.aggregate([
$unwind: "$types.flashcardReversed",
$project:
flashcardReversed: [
"$types.flashcardReversed.normal",
"$types.flashcardReversed.reversed"
]
,
$unwind: "$flashcardReversed",
$group:
_id: "$_id",
flashcardReversed: $push: "$flashcardReversed"
])
【讨论】:
感谢您的回答 - 我很感激。我注意到我的问题中有一个错误——因为我使用的是$facet
,所以我已经有了"flashcardReversed" as the parent: []
。我将如何在结果中返回 flashcardReversed
数组中的内容?
使用 $replaceRoot 阶段
已尝试,但出现错误 $replaceRoot must be of type object
。尝试使用 $arrayToObject,但我认为我需要一个不同的对象结构才能工作?
$replaceRoot:newRoot:"$flashcardReversed"
是的,正是我尝试过的,但仍然返回错误 - mongoplayground.net/p/CiaOOrzzw5i。目标是从数组中删除所有内容 - 因为 $facet 已经是一个数组 this 似乎它可能是一个解决方案以上是关于MongoDB聚合查询 - 返回嵌套子文档中的所有项目的主要内容,如果未能解决你的问题,请参考以下文章