我有那些收集模式
Schema.users = {
name : "string",
username : "string",
[...]
}
Schema.rooms = {
name : "string",
hidden: "boolean",
user: "string",
sqmt: "number",
service: "string"
}
Schema.room_price = {
morning : "string",
afternoon: "string",
day: "string",
room:'string'
}
我需要将用户与房间汇总在一起,并为每个房间汇总特定的房间价格。
预期结果将是
[{
_id:"xXXXXX",
name:"xyz",
username:"xyz",
rooms:[
{
_id: 1111,
name:'room1',
sqmt: '123x',
service:'ppp',
room_prices: [{morning: 123, afternoon: 321}]
}
]}]
聚合的第一部分可能是
db.collection('users').aggregate([
{$match: cond},
{$lookup: {
from: 'rooms',
let: {"user_id", "$_id"},
pipeline: [{$match:{expr: {$eq: ["$user", "$$user_id"]}}}],
as: "rooms"
}}])
但是我不知道如何在同一总数内获得房价
答案 0 :(得分:3)
假设String.Format
集合中的room
具有room_prices
集合中name
的匹配数据,则该表达式将匹配“内部” $lookup
表达式与另一个$lookup
的管道:
rooms
这还会在其中添加$project
,以便仅从价格中选择所需的字段。使用$lookup
的表达形式时,实际上确实可以表达“管道”,它可以是任何聚合管道组合。这样可以进行复杂的操作和类似的“嵌套查询”。
请注意,使用猫鼬还可以使用以下方法从模型对象获取集合名称:
db.collection('users').aggregate([
{ $match: cond },
{ $lookup: {
from: 'rooms',
let: { "user_id": "$_id" },
pipeline: [
{ $match:{ $expr: { $eq: ["$user", "$$user_id"] } } },
{ $lookup: {
from: 'room_prices',
let: { 'name': '$name' },
pipeline: [
{ $match: { $expr: { $eq: [ '$room', '$$name' } } },
{ $project: { _id: 0, morning: 1, afternoon: 1 } }
],
as: 'room_prices'
}}
],
as: "rooms"
}}
])
这通常是将来的证明,以防止可能的模型配置更改,这些更改可能会更改基础集合的名称。
在MongoDB 3.6及更高版本提供的子管道语法之前,您也可以使用 from: RoomPrice.collection.name
的“旧式”形式进行几乎相同的操作。只是更多的处理和重构:
$lookup
主要是使用$unwind
会带来更多开销,并且还要注意,“字段选择”实际上意味着您确实从 db.collection('users').aggregate([
{ $match: cond },
// in legacy form
{ $lookup: {
from: 'rooms',
localField: 'user_id',
foreignField: 'user',
as: 'rooms'
}},
// unwind the output array
{ $unwind: '$rooms' },
// lookup for the second collection
{ $lookup: {
from: 'room_prices',
localField: 'name',
foreignField: 'room',
as: 'rooms.room_prices'
}},
// Select array fields with $map
{ $addFields: {
'rooms': {
'room_prices': {
$map: {
input: '$rooms.room_prices',
in: {
morning: '$this.morning',
afternoon: '$this.afternoon'
}
}
}
}
}},
// now group back to 'users' data
{ $group: {
_id: '$_id',
name: { $first: '$name' },
username: { $first: '$username' },
// same for any other fields, then $push 'rooms'
rooms: { $push: '$rooms' }
}}
])
返回了“整个文档” “第一” < / em>,只有在完成后才能选择字段。
因此,较新的语法有很多优点,但是如果您愿意,也可以使用较早的版本。