我在MongoDB中遇到反向查找问题,并且没有单词来表达我想在Google搜索中做的事情。
例如,我有一个Client
集合。Order
集合具有对Client
的引用和一个对Salesman
的引用。
有没有办法:
- 获取包含其
orders
数组的所有clients
的列表(假设我们不在client
中存储引用数组? - 获取所有与乔治
salesman
打过交道clients
的名单?
数据看起来像
客户:
[
{_id: ObjectId('c1'), name:'blow', fname: 'joe'},
{_id: ObjectId('c2'), name:'smith', fname: 'john'},
]
订单:
[
{_id: ObjectId('o1'), item: 'wrench', client: ObjectId('c1'), salesman: ObjectId('s1')},
{_id: ObjectId('o2'), item: 'monkey wrench', client: ObjectId('c1'), salesman: ObjectId('s1')},
{_id: ObjectId('o2'), item: 'spanner', client: ObjectId('c1'), salesman: ObjectId('s2')}
]
推销员:
[
{_id: ObjectId('s1'), name:'smith', fname: 'terry'},
{_id: ObjectId('s2'), name:'wick', fname: 'john'},
]
在我列出clients
的查询中,我希望看到:
[
{_id: ObjectId('c1'), name:'blow', fname: 'joe', orders: [ObjectId('o1'), ObjectId('o2'), ObjectId('o3')]},
{_id: ObjectId('c2'), name:'smith', fname: 'john', orders: []}
]
在我希望看到的销售人员名单中:
[
{_id: ObjectId('s1'), name:'smith', fname: 'terry', clients: [ObjectId('c1')]},
{_id: ObjectId('s2'), name:'wick', fname: 'john', clients: [ObjectId('c1')]}
]
我已经看到了MongoDB的建议,在一对多关系中,我不应该在client
中保留可变的orders
数组,在salesman
中保留orders
/clients
,但我不知道如何执行那种"加入"我来自SQL背景。
在一个结构中,order
指的是client
和salesman
,反之亦然,我如何得到它?
也许有点晚了,但你可以像这样实现你的关系:
客户端查询:
- 加入收藏的第一$lookup
- 然后
$project
输出您想要的值。在这种情况下,使用$map
仅从每个_id
键中获取值进入"订单"。
db.clients.aggregate([
{
"$lookup": {
"from": "orders",
"localField": "_id",
"foreignField": "client",
"as": "orders"
}
},
{
"$project": {
"_id": 1,
"fname": 1,
"name": 1,
"orders": {
"$map": {
"input": "$orders",
"in": "$$this._id"
}
}
}
}
])
这里的例子
业务员查询:
同样的想法,使用第一个$lookup
进行连接,$map
来获取_ids
。同样在这里,您可以使用$setInteresection
来避免重复值。
db.salesmen.aggregate([
{
"$lookup": {
"from": "orders",
"localField": "_id",
"foreignField": "salesman",
"as": "clients"
}
},
{
"$addFields": {
"clients": {
"$setIntersection": {
"$map": {
"input": "$clients",
"in": "$$this.client"
}
}
}
}
}
])
这里的例子
其他查询
而且,要回答问题
获取所有与乔治
salesman
打过交道clients
的名单?
您可以使用两个$lookup
和两个$unwind
,如下所示:
- 首先
$match
只得到关于"推销员乔治"的查询。 - 然后加入"订单"收集。
$unwind
获取字段orders.client
并使用文档collection
再次加入($lookup
)。$unwind
一次又一次,$group
没有_id
让所有客户端都存在。
db.salesmen.aggregate([
{
"$match": {
"name": "George"
}
},
{
"$lookup": {
"from": "orders",
"localField": "_id",
"foreignField": "salesman",
"as": "orders"
}
},
{
"$unwind": "$orders"
},
{
"$lookup": {
"from": "clients",
"localField": "orders.client",
"foreignField": "_id",
"as": "clients"
}
},
{
"$unwind": "$clients"
},
{
"$group": {
"_id": null,
"clients": {
"$addToSet": "$clients"
}
}
}
])
这里的例子