我有一些这种格式的数据
[
{
"userId": 0,
"docId": 0,
"createdDate": "2024-03-20 09:22:24.492961"
},
{
"userId": 0,
"docId": 2,
"createdDate": "2024-03-20 09:22:24.492961"
},
{
"userId": 1,
"docId": 1,
"createdDate": "2024-01-15 09:22:24.492975"
},
{
"userId": 1,
"docId": 4,
"createdDate": "2024-01-15 09:22:24.492975"
},
{
"userId": 2,
"docId": 5,
"createdDate": "2024-01-15 09:22:24.492975"
}
]
我想订购这个,以便来自同一用户的两个文档不会一起返回。
预期结果
[
{
"userId": 0,
"docId": 0,
"createdDate": "2024-03-20 09:22:24.492961"
},
{
"userId": 2,
"docId": 5,
"createdDate": "2024-01-15 09:22:24.492975"
}
{
"userId": 1,
"docId": 1,
"createdDate": "2024-01-15 09:22:24.492975"
},
{
"userId": 0,
"docId": 2,
"createdDate": "2024-03-20 09:22:24.492961"
},
{
"userId": 1,
"docId": 4,
"createdDate": "2024-01-15 09:22:24.492975"
},
]
我尝试使用聚合管道按用户对项目进行分组,并仅获取第一个项目,然后获取第二个项目,但是当有数百个用户和数百个文档时,我想将其混合,使其不连续。本质上让它看起来是随机的。
如果您只想随机排序,规范的方法就是
$rand
设置随机字段并在其上 $sort
。
db.collection.aggregate([
{
"$set": {
"randomKey": {
"$rand": {}
}
}
},
{
"$sort": {
"randomKey": 1
}
},
{
"$set": {
"randomKey": "$$REMOVE"
}
}
])
从你的描述来看,它可以通过
$setWindowFields
实现(尽管在我看来并不完全“随机”)。
在
$setWindowFields
中,按 $userId
进行分区并计算 2 个字段,grouping
和 orderWithinGroup
。
- grouping
:该文档所属的分区。对于这个例子,我们只取 userId
- orderWithinGroup
:分区内的相对顺序。我们使用 $rank
来计算它
使用
$sort
的{"orderWithinGroup": 1, "grouping": 1}
,你应该能够实现想要的排序。
db.collection.aggregate([
{
"$setWindowFields": {
"partitionBy": "$userId",
"sortBy": {
"docId": 1
},
"output": {
"grouping": {
"$first": "$userId"
},
"orderWithinGroup": {
"$rank": {}
}
}
}
},
{
"$sort": {
"orderWithinGroup": 1,
"grouping": 1
}
},
{
"$set": {
"grouping": "$$REMOVE",
"orderWithinGroup": "$$REMOVE"
}
}
])