所以,这些是我的模型
let restaurantSchema = mongoose.Schema({
name: 'string',
restId: 'string',
saved: {type: 'date', default: Date.now()}
})
let userSchema = mongoose.Schema({
firstName: {type: 'string', default: ''},
lastName: {type: 'string', default: ''},
username: {
type: 'string',
required: true,
unique: true
},
beenTo: [restaurantSchema],
toGoTo: [restaurantSchema]
})
我要进行一次提要:“用户A要去餐馆X,用户B要去餐馆Y,用户A曾经去餐馆Z”,依此类推,这些都主要按日期排序。因此我一直在尝试使用aggregate来提供包含用户名和餐厅名称以及时间戳的文档,以便我可以对所有文档(无论用户名如何)都使用{'saved':-1进行排序}或任何时间戳记。
这是我到目前为止的收获
User.aggregate([
{$match: {username: {$ne: username}}},
{$lookup: {
from: "restaurants",
localField: "beenTo.saved",
foreignField: "saved",
as: "savRest"
}},
{$project: {'savRest.saved': 1, 'savRest.name': 1, 'username': 1}},
{$group: {
_id: null,
sav: {$push: '$savRest.saved'}
}}
])
考虑到数组,我希望在某个时候需要$ unwind,但是我不确定在管道中的哪个位置...
答案 0 :(得分:0)
我认为您需要重组schema
,并在用户文档中仅包括餐厅_id
,而不是将整个餐厅doc
作为sub-document
存储。 / p>
请将您的userSchema
更改为此:
let userSchema = mongoose.Schema({
firstName: {type: 'string', default: ''},
lastName: {type: 'string', default: ''},
username: {
type: 'string',
required: true,
unique: true
},
beenTo: [{type : mongoose.Schema.Types.ObjectId,ref : "Restaurant"}],
toGoTo: [{type : mongoose.Schema.Types.ObjectId,ref : "Restaurant"}]
})
请参阅我对您的架构所做的更改,而不是存储餐厅文档,我们将仅存储其_id(ObjectId)。
要获取所有餐厅并对其进行排序,您可以执行以下操作:
User.aggregate([
{$match: {username: {$ne: username}}},
// need to unwind the array, before we can do a $lookup over it
{$unwind : "beenTo"},
{$lookup: {
from: "restaurants",
localField: "beenTo",
foreignField: "_id",
as: "beenTo"
}},
//need to unwind again, as $lookup returns an array
{$unwind : "beenTo"},
//sort the result by beenTo.saved (date) first.
{$sort : {"$beenTo.saved" : -1}},
//after sorting, group all the docs and created sorted beenTo array
{
$group : {
_id : "$_id",
firstName : {$first : "$firstName"},
lastName : {$first : "$lastName"},
username : {$first : "$username"},
beenTo : {$push : "$beenTo"},
toGoTo : {$first : "$toGoTo"}
}
},
//after sorting of beenTo, we can go for sorting of toGoTo array,
// we will follow the same procedure again.
{$unwind : "toGoTo"},
{$lookup: {
from: "restaurants",
localField: "toGoTo",
foreignField: "_id",
as: "toGoTo"
}},
//need to unwind again, as $lookup returns an array
{$unwind : "toGoTo"},
{$sort : {"$toGoTo.saved" : -1}},
{
$group : {
_id : "$_id",
firstName : {$first : "$firstName"},
lastName : {$first : "$lastName"},
username : {$first : "$username"},
beenTo : {$first : "$beenTo"}
toGoTo : {$push : "$toGoTo"},
}
}
])
聚合管道的说明:
$match
:必须匹配所有选定的文档。$unwind
:我们需要先展开数组(beenTo
),然后才能对其进行查找。$lookup
:从餐厅收藏中填充受人尊敬的餐厅文档$unwind
:$lookup
返回一个数组,我们需要再次将其转换为对象。$sort
:根据beenTo.saved
值对所有文档进行排序$group
:基于用户的_id将所有文档分组,并将所有beenTo
文档推送到其数组中。 (现在,我们在beenTo
数组中填充了餐厅文档,并对其进行了排序)$unwind
:接下来,我们需要展开{{1}}数组,以便我们可以执行其查找toGoTo
:要填充餐厅收藏中的相应文档$lookup
:同样,我们需要放松,因为$unwind
返回一个数组$lookup
:根据toGoTo.saved字段对所有文档进行排序$sort
:基于用户$group
将所有文档分组,并将所有_id
文档推入其数组,而toGoTo
将保持不变。因此,在第11步结束时,我们将填充beenTo
和beenTo
的所有文档,并按保存日期进行排序。
希望这对您有所帮助。
请注意:在将餐厅添加到用户文档中的toGoTo
和beenTo
数组时,请仅按toGoTo
而不是完整的restaurant's _id
。