如何在此查询中使用 $isNull 到 return 空用户数组
How to use $isNull in this query to return empty Users array
给定一个使用时间戳的基本 Mongoose 用户模式(因此默认情况下 createdAt 和 updatedAt 可用),我正在尝试使用聚合构建一个包含分页服务器端的查询。
到目前为止,当数据库中有数据并且任何过滤器都与集合中的任何项目相匹配时,我已经实现了以下效果。
{
"users": [
{
"_id": "61c331f4bd87407c01b81324",
"bio": "",
"surname": "Doe",
"name": "John",
"verified": true,
"disabled": false,
"username": "user1235",
"score": 1
}
],
"pagination": {
"total": 1,
"limit": 10,
"page": 1,
"pages": 1
}
}
但是,如果没有项目符合条件,这只是 return 一个空数组,丢失分页部分。我的猜测是侧面部分没有像我预期的那样在这里工作。
const findUsersQuery = await this.userModel.aggregate()
.match(query)
.sort({ cratedAt: -1 })
.project({
password: 0, email: 0, roles: 0, __v: 0,
facebookId: 0, googleId: 0, createdAt: 0,
updatedAt: 0, birthday: 0
})
.facet({
total: [{
$count: 'createdAt'
}],
data: [{
$addFields: {
_id: '$_id'
}
}]
})
.unwind('$total')
.project({
users: {
$slice: ['$data', ((page * limit) - limit), {
$ifNull: [limit, '$total.createdAt']
}]
},
pagination: {
total: '$total.createdAt',
limit: {
$literal: limit
},
page: {
$literal: page
},
pages: {
$ceil: {
$divide: ['$total.createdAt', limit]
}
},
}
})
return findUsersQuery[0]
我曾尝试在某些地方使用 $ifNull,即使是在 facet 阶段,为了只是 return 0 或一个空数组到 return 相同的结构(保持用户数组和分页片), 无济于事:
.project({
users: {
$ifNull: [
{
$slice: ['$data', ((page * limit) - limit), {
$ifNull: [limit, '$total.createdAt']
}]
},
[]
]
},
pagination: {
total: {
$ifNull: ['$total.createdAt', 0]
},
limit: {
$literal: limit
},
page: {
$literal: page
},
pages: {
$ifNull: [
{
$ceil: {
$divide: ['$total.createdAt', limit]
}
},
0
]
},
}
})
如何使用 $ifNull(如果这是最好的方法)以便在没有项目符合条件时保持相同的响应结构?像这样:
{
"users": [],
"pagination": {
"total": 0,
"limit": 10,
"page": 1,
"pages": 1
}
}
非常感谢任何帮助。
你不需要在这里使用$ifNull
,你的问题源于$unwind行为。
您想在 $unwind
中使用 preserveNullAndEmptyArrays
New in version 3.2: To output documents where the array field is missing, null or an empty array, use the preserveNullAndEmptyArrays option.
这将保留文档,即使它是“空的”,如下所示:
.unwind({
path: "$total",
preserveNullAndEmptyArrays: true
})
给定一个使用时间戳的基本 Mongoose 用户模式(因此默认情况下 createdAt 和 updatedAt 可用),我正在尝试使用聚合构建一个包含分页服务器端的查询。
到目前为止,当数据库中有数据并且任何过滤器都与集合中的任何项目相匹配时,我已经实现了以下效果。
{
"users": [
{
"_id": "61c331f4bd87407c01b81324",
"bio": "",
"surname": "Doe",
"name": "John",
"verified": true,
"disabled": false,
"username": "user1235",
"score": 1
}
],
"pagination": {
"total": 1,
"limit": 10,
"page": 1,
"pages": 1
}
}
但是,如果没有项目符合条件,这只是 return 一个空数组,丢失分页部分。我的猜测是侧面部分没有像我预期的那样在这里工作。
const findUsersQuery = await this.userModel.aggregate()
.match(query)
.sort({ cratedAt: -1 })
.project({
password: 0, email: 0, roles: 0, __v: 0,
facebookId: 0, googleId: 0, createdAt: 0,
updatedAt: 0, birthday: 0
})
.facet({
total: [{
$count: 'createdAt'
}],
data: [{
$addFields: {
_id: '$_id'
}
}]
})
.unwind('$total')
.project({
users: {
$slice: ['$data', ((page * limit) - limit), {
$ifNull: [limit, '$total.createdAt']
}]
},
pagination: {
total: '$total.createdAt',
limit: {
$literal: limit
},
page: {
$literal: page
},
pages: {
$ceil: {
$divide: ['$total.createdAt', limit]
}
},
}
})
return findUsersQuery[0]
我曾尝试在某些地方使用 $ifNull,即使是在 facet 阶段,为了只是 return 0 或一个空数组到 return 相同的结构(保持用户数组和分页片), 无济于事:
.project({
users: {
$ifNull: [
{
$slice: ['$data', ((page * limit) - limit), {
$ifNull: [limit, '$total.createdAt']
}]
},
[]
]
},
pagination: {
total: {
$ifNull: ['$total.createdAt', 0]
},
limit: {
$literal: limit
},
page: {
$literal: page
},
pages: {
$ifNull: [
{
$ceil: {
$divide: ['$total.createdAt', limit]
}
},
0
]
},
}
})
如何使用 $ifNull(如果这是最好的方法)以便在没有项目符合条件时保持相同的响应结构?像这样:
{
"users": [],
"pagination": {
"total": 0,
"limit": 10,
"page": 1,
"pages": 1
}
}
非常感谢任何帮助。
你不需要在这里使用$ifNull
,你的问题源于$unwind行为。
您想在 $unwind
preserveNullAndEmptyArrays
New in version 3.2: To output documents where the array field is missing, null or an empty array, use the preserveNullAndEmptyArrays option.
这将保留文档,即使它是“空的”,如下所示:
.unwind({
path: "$total",
preserveNullAndEmptyArrays: true
})