mongodb mongo 组查询如何保留字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16662405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 13:14:20  来源:igfitidea点击:

mongo group query how to keep fields

mongodb

提问by plusor

Everybody. In mongo group query, the result shows only the key(s) in arguments. How to keep the first document in each group like mysql query group. for example:

大家。在 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 } })

result:

结果:

[
{
    "name" : "ddl1st",
    "count" : 1
},
{
    "name" : "24k",
    "count" : 1
}
]

How to get the following:

如何获得以下内容:

[
   {
   "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
}
]

回答by MervS

If you want to keep the information about the first matching entries for each group, you can try aggregating like:

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

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 }
  }
}

回答by u5189296

By the way, if you want to keep not only the first document, you can use$addToSetFor example:

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

db.test.aggregate({
  $group: {
    _id: '$name',
    name : { $addToSet: '$name' }
    age : { $addToSet: '$age' },
    count: { $sum: 1 }
  }
}

回答by Pieter

I came here looking for an answer but wasn't happy with the selected answer (especially given it's age). I found this answerthat is a better solution (adapted):

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

db.test.aggregate({
  $group: {
    _id: '$name',
   person: { "$first": "$$ROOT" },
   count: { $sum: 1 }
  },
  {
    "$replaceRoot": { "newRoot": "$person" }
  }
}

回答by Deeksha Sharma

You can try out this

你可以试试这个

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

}

回答by Thavaprakash Swaminathan

This is what i did, it works fine.

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

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 
  }
}])

回答by Matt Wills

I created this function to generalise reversing an unwind stage... let me know if you guys come across any bugs with it, but it's working well for me!

我创建了这个函数来概括反转放松阶段……如果你们遇到任何错误,请告诉我,但它对我来说效果很好!

const createReverseUnwindStages = unwoundField => {
  const stages = [
    //
    // Group by the unwound field, pushing each unwound value into an array,
    //
    // Store the data from the first unwound document
    // (which should all be the same apart from the unwound field)
    // on a field called data.
    // This is important, since otherwise we have to specify every field we want to keep individually.
    //
    {
      $group: {
        _id: '$_id',
        data: {$first: '$$ROOT'},
        [unwoundField]: {$push: `$${unwoundField}`},
      },
    },

    //
    // Copy the array of unwound fields resulting from the group into the data object,
    // overwriting the singular unwound value
    //
    {
      $addFields: {[`data.${unwoundField}`]: `$${unwoundField}`},
    },

    //
    // Replace the root with our data object
    //
    {
      $replaceRoot: {
        newRoot: '$data',
      },
    },
  ]

  return stages
}

回答by Gary Wild

Just a quick update if one faces the same issue with documents with numerous fields. One can use the power of combining the $replaceRootpipeline stage and the $mergeObjectspipeline operator.

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

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

回答by Ashh

Use $firstwith the $$ROOTdocument and then use $replaceRootwith the first field.

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

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

回答by gustavohenke

I didn't know about .grouphelper, but if you prefer to go with the Aggregation Framework, then you'll have to specify which fields to return. Correct me if I'm wrong, but in SQL you would have to do that anyway.

我不知道.grouphelper,但是如果您更喜欢使用Aggregation Framework,那么您必须指定要返回的字段。如果我错了,请纠正我,但在 SQL 中,无论如何您都必须这样做。

Well, this is how you would do it with the Aggregation Framework mentioned before:

好吧,这就是您如何使用前面提到的聚合框架来做到这一点:

db.test.aggregate({
  $group: {
    _id: { name: "$name", city: "$city", fieldName: "$fieldName" },
    count: { $sum: 1 }
  }
})

回答by Pankaj Cheema

Here is the answer >>>>

答案在这里>>>

    $m = new \MongoDB\Driver\Manager();

    $command = new \MongoDB\Driver\Command([
        'aggregate' => 'mytestusers',
        'pipeline' => [
            ['$match' => ['name' => 'Pankaj Choudhary']],

            ['$unwind'=>'$skills'],
            ['$lookup' => array('from'=>'mytestskills','localField'=>'skills','foreignField'=>'_id','as'=>'sdfg')],
            ['$unwind'=>'$sdfg'],

            ['$group'=>array('_id'=>array('_id'=>'$_id','name'=>'$name','email'=>'$email'),'skills'=>array('$push'=>'$skills'),'sdfg'=>array('$push'=>'$sdfg'))],


        ],
        'cursor' => new \stdClass,
    ]);
    $cursor = $m->executeCommand('targetjob-plus', $command);
    $result = $cursor->toArray();