首页 > 解决方案 > 在 MongoDb 中使用 addToSet 时保持原始文档的顺序

问题描述

我阅读了文档,发现 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"}]
                      
                    }
            
           
}

我想保持与原始文档相同的顺序,每次文档都会更改,所以我不能根据任何参数进行排序。

标签: mongodbmongoosemongodb-queryaggregation-framework

解决方案


  • 使用将结果对象转换为数组格式$objectToArray
  • $unwind解构Results数组
  • $unwind解构Results.v.TCR数组
  • $match过滤PASSED结果
  • $groupby Results.kand get first Name, get first Counters, 构造数组Results.v.TCR
  • $group通过 null 并获取最小值Time,构造唯一数组,在键值对中构造数组,No迭代循环并删除重复文档Results$reduceTCR
  • $project显示必填字段,Results使用将数组转换为对象$arrayToObject,将无数组转换为字符串并使用“-”连接
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"
              ]
            }
          }
        }
      }
    }
  }
])

操场

这 ”。” (点)在“不”。字段无效,可能会导致 mongodb 查询操作出现问题,我建议不要使用“。” (点)作为字段名称。


推荐阅读