在 MongoDb 中使用 addToSet 时保持原始文档的顺序
Posted
技术标签:
【中文标题】在 MongoDb 中使用 addToSet 时保持原始文档的顺序【英文标题】:Maintain order as original document while using addToSet in MongoDb 【发布时间】:2021-07-09 04:33:16 【问题描述】:我阅读了文档,发现 addToSet 不保证顺序。 但是有什么办法可以将订单保留为原始文档。 我的查询是:-
aggregate([$match:
$or:["Name.No":"119","Name.No":"120"]
, $project:
x:$objectToArray:"$Results"
,$unwind: "$x",$group: _id: "$x.k", distinctVals: $addToSet: "$x.v.TCR"])
样本数据:
"Name" : "No." : "119","Time" : "t",
"Results":"K1" : "Counters" : x, "TCR" : ["Name" : "K11", "Result" : "PASSED",
"Name" : "K12","Result" : "FAILED",
"Name" : "K13","Result" : "PASSED"]
,
"K2" : "Counters": y, "TCR" : ["Name" : "K21","Result" : "PASSED",
"Name" : "K22","Result" : "PASSED"]
工作2;
"Name" : "No." : "120","Time" : "t1",
"Results":"K1" : "Counters" : x, "TCR" : ["Name" : "K11", "Result" : "PASSED",
"Name" : "K12","Result" : "PASSED",
"Name" : "K13","Result" : "FAILED"]
,
"K3" : "Counters": y, "TCR" : ["Name" : "K31","Result" : "PASSED",
"Name" : "K32","Result" : "PASSED"]
预期;
"Name" : "No." : "119-120","Time" : "lowest(t,t1)",
"Results":"K1" : "Counters" : x, "TCR" : ["Name" : "K11", "Result" : "PASSED",
"Name" : "K12","Result" : "PASSED",
"Name" : "K13","Result" : "PASSED"]
,
"K2" : "Counters": y, "TCR" : ["Name" : "K21","Result" : "PASSED",
"Name" : "K22","Result" : "PASSED"]
,
"K3" : "Counters": y, "TCR" : ["Name" : "K31","Result" : "PASSED",
"Name" : "K32","Result" : "PASSED"]
我想保持与原始文档相同的顺序,而且每次文档都会更改,所以我无法根据任何参数进行排序。
【问题讨论】:
您能否在查询中添加示例数据mongoplayground.net 如何定义顺序?假设您输入的是[20, 10, 20]
。你想得到什么输出? [10, 20]
还是 [20,10]
?来自@turivishal 的解决方案给出了[20,10]
添加了现在有问题的示例数据。
【参考方案1】:
使用$objectToArray
将结果对象转换为数组格式
$unwind
解构Results
数组
$unwind
解构Results.v.TCR
数组
$match
过滤PASSED
结果
$group
by Results.k
并获得第一个Name
,获得第一个Counters
,构造Results.v.TCR
的数组
$group
by null 得到最小值Time
,构造No
的唯一数组,在键值对中构造Results
数组,$reduce
迭代TCR
的循环并删除重复文档
$project
显示必填字段,使用 $arrayToObject
将 Results
数组转换为对象,将 No 数组转换为字符串并使用“-”连接
db.collection.aggregate([
$addFields: Results: $objectToArray: "$Results" ,
$unwind: "$Results" ,
$unwind: "$Results.v.TCR" ,
$match: "Results.v.TCR.Result": "PASSED" ,
$group:
_id: "$Results.k",
Name: $first: "$Name" ,
Counters: $first: "$Results.v.Counters" ,
TCR: $push: "$Results.v.TCR"
,
$group:
_id: null,
Time: $min: "$Name.Time" ,
No: $addToSet: "$Name.No" ,
Results:
$push:
k: "$_id",
v:
Counters: "$Counters",
TCR:
$reduce:
input: "$TCR",
initialValue: [],
in:
$cond: [
$in: [
Name: "$$this.Name",
Result: "$$this.Result"
,
"$$value"
]
,
"$$value",
$concatArrays: [
"$$value",
[
Name: "$$this.Name",
Result: "$$this.Result"
]
]
]
,
$project:
_id: 0,
Results: $arrayToObject: "$Results" ,
Name:
Time: "$Time",
No:
$reduce:
input: "$No",
initialValue: "",
in:
$concat: [
"$$value",
$cond: [ $eq: ["$$value", ""], "", "-"] ,
"$$this"
]
])
Playground
“。” (点)在“不”。字段无效,可能会导致 mongodb 查询操作出现问题,我建议不要使用“。” (点)作为字段名。
【讨论】:
no..还是不行,push也没有保留订单。 您能否在您的问题中发布示例文档和预期结果。 使用示例数据更新了问题 根据您的查询,您的文档无效,您确定Results
已经是数组吗?因为您已使用 x:$objectToArray:"$Results"
将其从对象转换为数组,因此不需要 $project 阶段。
您现在可以检查一下吗以上是关于在 MongoDb 中使用 addToSet 时保持原始文档的顺序的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB聚合,如何在组管道中addToSet数组的每个元素