Sorting records in a way so that only records which matches an id comes first?

大城市里の小女人 提交于 2021-01-28 22:05:02

问题


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 check createdBy is matching return 1 otherwise 0,
  • $sort by matchResult 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!