问题
I have a query which return me the records or messages for a certain scenario:
const [messages, messageCount] = await Promise.all([
MessageModel.find(params).select(filterObject).limit(ctx.query.limit).skip(ctx.paginate.skip)
.sort('-sex -age')
.lean(),
MessageModel.countDocuments(params),
]);
Is there any way to get the records first which matches an object id, and then rest of the records?
Result
{
_id:abc0aa8573bfa917b152cdbc
isPrivate:false
message:"My name is stark"
gender:"unisex"
age: "19"
createdBy:abcff9ef71fa048cea3c8a97
}
{
_id:abc0aa8573bfa917b152cdbc
isPrivate:false
message:"My name is james"
gender:"unisex"
age: "20"
createdBy:defff9ef71fa048cea3c8a97
}
{
_id:abc0aa8573bfa917b152cdbc
isPrivate:false
message:"My name is harry"
gender:"unisex"
age: "20"
createdBy:defff9ef71fa048cea3c8a97
}
{
_id:abc0aa8573bfa917b152cdbc
isPrivate:false
message:"My name is max"
gender:"unisex"
age: "20"
createdBy:abcff9ef71fa048cea3c8a97
}
Now I want those messages that was created by the abc... first. All those records that match a certain id would come first and then rest of the records would remain the same
{
_id:abc0aa8573bfa917b152cdbc
isPrivate:false
message:"My name is stark"
gender:"unisex"
age: "19"
createdBy:abcff9ef71fa048cea3c8a97
}
{
_id:abc0aa8573bfa917b152cdbc
isPrivate:false
message:"My name is max"
gender:"unisex"
age: "20"
createdBy:abcff9ef71fa048cea3c8a97
}
{
_id:abc0aa8573bfa917b152cdbc
isPrivate:false
message:"My name is james"
gender:"unisex"
age: "20"
createdBy:defff9ef71fa048cea3c8a97
}
{
_id:abc0aa8573bfa917b152cdbc
isPrivate:false
message:"My name is harry"
gender:"unisex"
age: "20"
createdBy:defff9ef71fa048cea3c8a97
}
回答1:
I don't think there is any straight way to do this, If you really want to then try $cond
operator to check condition on specific field,
- add new field
matchResult
in$project
it will checkcreatedBy
is matching return 1 otherwise 0, $sort
bymatchResult
in descending order
const [messages, messageCount] = await Promise.all([
MessageModel.aggregate([
{ $match: params },
{
$project: {
...filterObject,
matchResult: {
$cond: [
{ $eq: ["$createdBy", ObjectId("abcff9ef71fa048cea3c8a97")] },
1,
0
]
}
}
},
{ $sort: { matchResult: -1 } },
{ $skip: ctx.paginate.skip },
{ $limit: ctx.query.limit }
]),
MessageModel.countDocuments(params),
]);
Playground
Second option is $regexMatch aggregation operator starting from MongoDB v4.2,
Playground
I am not recommending this approach for big data in collection, this may cause performance issue, it is better to sort in your client side after query.
来源:https://stackoverflow.com/questions/65608677/sorting-records-in-a-way-so-that-only-records-which-matches-an-id-comes-first