我有这个问题:
我需要进行查询,以获取外国数据(通过查询),“多对多”和“一对多”。
我的数据如下:
转移收藏集:
{
"_id": 1,
"requests": [
{
"service": 1,
"foo": "foo1",
"bar": "bar1"
},
{
"service": 2,
"foo": "foo2",
"bar": "bar2"
}
]
}
因此,“服务”字段是另一个集合“服务”的外部ID。
服务集合:
[{ _id: 1, name: 'Service 1" }, { _id: 2, name: 'Service 2' }]
问题是:如何在“转移”集合中按服务名称过滤?我知道猫鼬的填充,但是这不允许按外部数据进行过滤(而且,我的函数需要分页(我使用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"
}
]
}
答案 0 :(得分:2)
这是一种解决方案-暂时不确定这是否是最漂亮的方法,但肯定可以完成工作:
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" ] } }
]
}
}
}
}
}])
我从来没有真正比较过两个版本的性能,但是我怀疑第二个版本会更快。