在MongoDB中创建值和出现次数的聚合列表

xnifntxz  于 2023-11-17  发布在  Go
关注(0)|答案(1)|浏览(285)

鉴于以下文件:

  1. [
  2. {
  3. _id: "N0001",
  4. name: "Bruce Lee",
  5. skills: ["karate", "jiu jitsu"],
  6. },
  7. {
  8. _id: "N0002",
  9. name: "Bruce Dee",
  10. skills: ["karate", "tae kwon do"],
  11. },
  12. {
  13. _id: "N0003",
  14. name: "Bruce See",
  15. skills: ["aikido", "jiu jitsu"],
  16. },
  17. {
  18. _id: "N0004",
  19. name: "Deuce Lee",
  20. skills: ["karate", "judo"],
  21. },
  22. ]

字符串
我想得到以下信息:

  1. {
  2. karate: 3,
  3. jiu jitsu: 2,
  4. tae kwon do: 1,
  5. judo: 1,
  6. aikido: 1,
  7. }


现在,我可以用下面这样的脚本来获得上面的内容:

  1. const uniqueSkills = db.fighters.distinct('skills');
  2. console.log(
  3. Object.fromEntries(
  4. uniqueSkills.map(
  5. async m => [m, await db.fighters.find({ skills: m }).length]
  6. )
  7. )
  8. )


但是我真的很想把这整个事情保持在聚合框架内,而不是使用节点运行时来重复进行这个查询,我完全不知道如何做到这一点。注意,技能集是有限的,但未知的,所以我不能从已知的技能列表开始,然后把它们硬编码到查询本身中。

vlurs2pr

vlurs2pr1#

这样做的一种方法如下:

  1. db.collection.aggregate([
  2. {
  3. $unwind: "$skills"
  4. },
  5. {
  6. $group: {
  7. _id: "$skills",
  8. count: {
  9. $sum: 1
  10. }
  11. }
  12. },
  13. {
  14. $group: {
  15. _id: null,
  16. skills: {
  17. "$addToSet": {
  18. k: "$_id",
  19. v: "$count"
  20. }
  21. }
  22. }
  23. },
  24. {
  25. "$replaceRoot": {
  26. "newRoot": {
  27. "$arrayToObject": "$skills"
  28. }
  29. }
  30. }
  31. ])

字符串
使用示例输入的输出为:

  1. {
  2. "aikido": 1,
  3. "jiu jitsu": 2,
  4. "judo": 1,
  5. "karate": 3,
  6. "tae kwon do": 1
  7. }


我们在这里:

  1. $unwind执行skills数组以获取各个条目。
  2. $group将这些技能组合在一起以获得计数
  3. $group将这些组组合在一起,以将所有条目放入单个文档中
    1.使用$replaceRoot重塑文档。
    第三步和第四步是为了利用the $arrayToObject operator而设计的。
    看看它在this playground example中是如何工作的。
    我很确定还有其他方法可以做到这一点。同样需要注意的是,随着数据集的增长,这种操作将是资源密集型的,但这只是像这样的分析操作必须针对该模式运行的自然结果。
展开查看全部

相关问题