mongo group查询如何保留字段

plu*_*sor 70 mongodb

每个人.在mongo组查询中,结果仅显示参数中的键.如何将每个组中的第一个文档保存为mysql查询组.例如:

-------------------------------------------------------------------------
|  name  | age  |  sex  | province |   city   |   area   |   address     |
-------------------------------------------------------------------------
| ddl1st | 22   | ??? |  BeiJing |  BeiJing | ChaoYang | QingNianLu    |
| ddl1st | 24   | ??? |  BeiJing |  BeiJing | XuHui    | ZhaoJiaBangLu |
|  24k   | 220  | ...   |  ....    |  ...     | ...      | ...           |
-------------------------------------------------------------------------



db.users.group({key: { name: 1},reduce: function ( curr, result ) { result.count ++ },initial: {count : 0 } })
Run Code Online (Sandbox Code Playgroud)

结果:

[
{
    "name" : "ddl1st",
    "count" : 1
},
{
    "name" : "24k",
    "count" : 1
}
]
Run Code Online (Sandbox Code Playgroud)

如何获得以下内容:

[
   {
   "name" : "ddl1st",
   "age" : 22,
   "sex" : "???",
   "province" : "BeiJing",
   "city" : "BeiJing",
   "area" : "ChaoYang",
   "address" : "QingNianLu",
   "count" : 1
   },
   {
   "name" : "24k",
   "age" : 220,
   "sex" : "...",
   "province" : "...",
   "city" : "...",
   "area" : "...",
   "address" : "...",
   "count" : 1
}
]
Run Code Online (Sandbox Code Playgroud)

Mer*_*rvS 181

如果要保留每个组的第一个匹配条目的信息,可以尝试聚合,如:

db.test.aggregate({
  $group: {
    _id: '$name',
   name : { $first: '$name' }
   age : { $first: '$age' },
   sex : { $first: '$sex' },
   province : { $first: '$province' },
   city : { $first: '$city' },
   area : { $first: '$area' },
   address : { $first: '$address' },
   count: { $sum: 1 }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果不是将这个聚合计算为年龄的最大值或最小值,该怎么办?$ first不一定与其他字段的最小或最大年龄相匹配。那该如何处理呢? (3认同)
  • 为什么你需要`{$ first:'$ age'}`等?是否有可能只有'年龄:$ age`? (2认同)
  • @lightalchemist这是不可能的.让"团队"知道选择什么是一种技巧. (2认同)
  • 这不起作用,它按其他不需要的字段分组。 (2认同)
  • @Juliomac,我相信如果您想要的输出是 $max/$min 并保留不在 `$group` _id 中的字段,您可以在所需字段之前使用 `$sort` 然后分组并使用 `$first` 或 `任何字段上的 $last` 运算符。在积累时,包括其他字段(积累/漏斗/减少)的想法即使在理论上也没有多大意义。然而,与对每个组内部进行排序相比,预先排序实际上效率较低,因为排序算法比 O(n) 更复杂。我希望 MongoDB 能有更好的方法。 (2认同)

Pie*_*ter 25

[编辑以包含评论建议]

我来到这里寻找答案,但对所选答案不满意(特别是考虑到它的年龄)。我发现这个答案是一个更好的解决方案(改编):

db.test.aggregate({
  $group: {
    _id: '$name',
   person: { "$first": "$$ROOT" },
   count: { $sum: 1 }
  },
  {
    "$replaceRoot": { "newRoot": { "$mergeObjects": ["$person", { count: "$count" }]} }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 为了详细说明 0zkr 关于使用 $mergeObjects 的评论并帮助其他人使用语法,最后的管道语法将是 `{"$replaceRoot": {"newRoot": {"$mergeObjects": ["$person", {count: " $count"}]}}}` (4认同)
  • 但是,您丢失了“count”字段。您需要使用“$mergeObjects”来保留它。 (3认同)

Dee*_*rma 11

你可以试试这个

db.test.aggregate({
      { $group: 
            { _id: '$name',count: { $sum: 1 }, data: { $push: '$$ROOT' } } },
      {
        $project: {
          _id:0,
          data:1,
          count :1
        }
      }

}
Run Code Online (Sandbox Code Playgroud)


小智 7

顺便说一句,如果您不仅要保留第一个文档,还可以使用$ addToSet 例如:

db.test.aggregate({
  $group: {
    _id: '$name',
    name : { $addToSet: '$name' }
    age : { $addToSet: '$age' },
    count: { $sum: 1 }
  }
}
Run Code Online (Sandbox Code Playgroud)


Ash*_*shh 7

使用$first$$ROOT文档,然后用$replaceRoot与第一场。

db.test.aggregate([
  { "$group": {
    "_id": "$name",
    "doc": { "$first": "$$ROOT" }
  }},
  { "$replaceRoot": { "newRoot": "$doc" }}
])
Run Code Online (Sandbox Code Playgroud)


Tha*_*han 5

这就是我所做的,它工作正常。

db.person.aggregate([
{
  $group: { _id: '$name'}, // pass the set of field to be grouped
   age : { $first: '$age' }, // retain remaining field
   count: { $sum: 1 } // count based on your group
},
{
  $project:{
       name:"$_id.name",
       age: "$age",
       count: "$count",
       _id:0 
  }
}])
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您在处理包含多个字段的文档时遇到同样的问题,只需快速更新即可。可以使用组合$replaceRoot流水线阶段和$mergeObjects流水线操作符的力量。

db.users.aggregate([
  {
    $group: {
      _id: '$name',
      user: { $first: '$$ROOT' },
      count: { $sum: 1 }
    },
  },
  {
    $replaceRoot: {
      newRoot: { $mergeObjects: [{ count: '$count' }, '$user'] }
    }
  }
])
Run Code Online (Sandbox Code Playgroud)