MongoDB聚合查找和展开[重复]
Posted
技术标签:
【中文标题】MongoDB聚合查找和展开[重复]【英文标题】:MongoDB Aggregate Lookup and Unwind [duplicate] 【发布时间】:2019-03-04 20:26:19 【问题描述】:我有这个问题:
我需要进行查询,获取外部数据(通过查找)、“多对多”和“一对多”。
我的数据看起来是这样的:
转让收藏:
"_id": 1,
"requests": [
"service": 1,
"foo": "foo1",
"bar": "bar1"
,
"service": 2,
"foo": "foo2",
"bar": "bar2"
]
所以,“service”字段,是另一个集合“services”的外部ID。
服务集合:
[ _id: 1, name: 'Service 1" , _id: 2, name: 'Service 2' ]
问题是:如何在 Transfer 集合中按服务名称进行过滤?我知道 mongoose 的填充,但这不允许通过外部数据进行过滤(另外,我的函数需要分页(我使用 mongoose-pagination 插件),因此,我在执行后丢弃过滤,因为这可以过滤少量数据宇宙)。
我相信最好的选择是使用聚合。 但是,如果我做这个......
db.transfers.aggregate([
$lookup:
from: 'services',
localField: 'requests.service',
foreignField: '_id',
as: 'requests.service'
])
我知道了:
"_id" : 1,
"requests" :
"service" : [
"_id" : 1,
"name" : "Service 1"
,
"_id" : 1,
"name" : "Service 2"
]
如何在不改变查询的情况下将服务数据放入主体对象中?
显然,聚合函数在“请求”(很多)上添加了“展开”,而不是在“服务”(一个)上添加了“展开”
无论如何,我需要这个返回的数据:
"_id" : 1,
"requests": [
"service":
"_id" : 1,
"name" : "Service 1"
,
"foo": "foo1",
"bar": "bar1"
,
"service":
"_id" : 2,
"name" : "Service 2"
,
"foo": "foo2",
"bar": "bar2"
]
【问题讨论】:
所以您正试图让服务名称包含在每个request
对象中?
【参考方案1】:
这是一种解决方案 - 现在不确定它是否是最漂亮的,但它确实可以完成工作:
db.transfers.aggregate([
$lookup:
from: 'services',
localField: 'requests.service',
foreignField: '_id',
as: 'requests2'
,
$project:
"requests":
$map:
"input":
$zip:
"inputs": [ "$requests", "$requests2" ]
,
"as": "this",
"in":
$mergeObjects: [
$arrayElemAt: [ "$$this", 0 ] ,
"service": $arrayElemAt: [ "$$this", 1 ]
]
])
第二种选择是这样做:
db.transfers.aggregate([
$lookup:
from: 'services',
localField: 'requests.service',
foreignField: '_id',
as: 'requests2'
,
$project:
"requests":
$map:
"input":
$range: [ 0, $size: "$requests2" ]
,
"as": "index",
"in":
$mergeObjects: [
$arrayElemAt: [ "$requests", "$$index" ] ,
"service": $arrayElemAt: [ "$requests2", "$$index" ]
]
])
我从未真正比较过这两个版本的性能,但我怀疑第二个版本要快一些。
【讨论】:
以上是关于MongoDB聚合查找和展开[重复]的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB,如何将查找和排序与聚合中的 $cond 结合起来?