我有 mongo 文档列表
[
{
"created_at": "2024-03-15T18:11:18.687",
"updated_at": "2024-03-15T18:11:28.945",
"fields": {
"contract_first": [],
"contract_second": [
{
"position": "Bob"
}
],
"uuid": "bf031b46-ec33-4c61-ad33-a3ad2cbeb9cb"
},
"id": "65f46520928f6fd496ffbe6d"
},
{
"created_at": "2024-03-15T18:11:18.687",
"updated_at": "2024-03-15T18:15:26.838",
"fields": {
"contract_first": [
{
"position": "Anna"
}
],
"contract_second": [],
"uuid": "bf052b46-ec33-4c61-ad33-a3ad2cbeb9cb"
},
"id": "65f4660e928f6fd496ffbeb0"
},
{
"created_at": "2024-03-15T18:11:18.687",
"updated_at": "2024-03-15T18:15:26.838",
"fields": {
"contract_first": [
{
"position": "Bob"
}
],
"contract_second": [],
"uuid": "bf092b46-ec33-4c61-ad33-a3ad2cbeb9cb"
},
"id": "65f8660e928f6fd496ffbeb0"
}
]
其中有 2 个主要数组字段
contract_first
和 contract_second
,我想知道如何按 2 个数组字段对我的文档进行排序?
我正在尝试使用
{
'$sort': {
'fields.contract_first.position': 1,
'fields.contract_second.position': 1
}
}
但是我有一个错误
cannot sort with keys that are parallel arrays
例如输出应该是这样的: 安娜 鲍勃 鲍勃 即使他们在不同的领域
从 mongoDB 5.2 版本开始,一种选择是:
db.collection.aggregate([
{$set: {sort_key: {$sortArray: {
input: {
$concatArrays: [
"$fields.contract_first.position",
"$fields.contract_second.position"
]
},
sortBy: 1
}}}},
{$sort: {sort_key: 1}},
{$unset: "sort_key"}
])
即使在
{ contract_first: [{ position: "Ellen" }], contract_second: [] }
vs { contract_first: [], contract_second: [{ position: "Dave" }] }
的情况下,我也希望“Dave”位于“Ellen”之前
如果只有第一个或第二个合约有一个条目,但不是两者都有,那么你可以这样做:
根据每个值的第一个非空值分配一个 sort_key,然后根据该值进行排序。
db.collection.aggregate([
{
$set: {
sort_key: {
$ifNull: [
{ $first: "$fields.contract_first.position" },
{ $first: "$fields.contract_second.position" }
]
}
}
},
{ $sort: { sort_key: 1 } }
])
但是,如果第一个和第二个合约都可以存在,您需要将第二个合约重新添加为 sort_key。
所以在这里,我创建了其中两个:
sort_key1
是第一个非空合约,位置在first_contract
和second_contract
之间,而sort_key2
只是second_contract
。因此,当 sort_key2
相同时,将使用 sort_key1
。
db.collection.aggregate([
{
$set: {
sort_key1: {
$ifNull: [
{ $first: "$fields.contract_first.position" },
{ $first: "$fields.contract_second.position" }
]
},
sort_key2: { $first: "$fields.contract_second.position" }
}
},
{
$sort: {
sort_key1: 1,
sort_key2: 1
}
},
{
// comment this out to see the sort_keys
$unset: ["sort_key1", "sort_key2"]
}
])
对于涉及自定义排序逻辑的用例,常见的解决方案模式之一是创建自定义排序键并对其进行排序。这提供了灵活性,因为如果情况发生变化,您可以简单地更新排序键的逻辑。
对于您的情况,我创建了一个具有以下逻辑的
sortKey
:
contract_first.position
,如果为空,$ifNull
回退到MaxKey(MongoDB中排序的最大类型,请参阅this doc,或者您可以使用任何您确定会大于的值该字段中可能的值)contract_second.position
,如果为空,$ifNull
回退到MaxKey$min
创建排序键后,只需对结果进行排序即可。使用后请随意删除排序键。如果您不想经常计算密钥,您可以具体化/保留密钥。
db.collection.aggregate([
{
"$set": {
"sortKey": {
"$min": [
{
"$ifNull": [
{
"$first": "$fields.contract_first.position"
},
{
"$maxKey": 1
}
]
},
{
"$ifNull": [
{
"$first": "$fields.contract_second.position"
},
{
"$maxKey": 1
}
]
}
]
}
}
},
{
"$sort": {
"sortKey": 1
}
},
{
"$unset": "sortKey"
}
])