mongo group query खेतों को कैसे रखें


97

सब लोग। मोंगो समूह क्वेरी में, परिणाम तर्कों में केवल कुंजी दिखाता है। Mysql query group जैसे प्रत्येक समूह में पहला दस्तावेज़ कैसे रखें। उदाहरण के लिए:

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

परिणाम:

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

निम्नलिखित कैसे प्राप्त करें:

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

जवाबों:


215

यदि आप प्रत्येक समूह के लिए पहली मिलान प्रविष्टियों के बारे में जानकारी रखना चाहते हैं, तो आप इस तरह की कोशिश कर सकते हैं:

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

3
आपको {$first: '$age'}आदि की आवश्यकता क्यों है ? क्या यह संभव है age: $age?
लाइटकेमिस्ट

7
@lightalchemist यह संभव नहीं है। यह एक चाल की तरह है 'समूह' को पता है कि क्या चुनना है।
TechWisdom

4
क्या होगा अगर गिनती के बजाय यह एकत्रीकरण $ अधिकतम या $ मिनट की उम्र के लिए कर रहा था? $ पहले जरूरी नहीं कि अन्य क्षेत्रों के लिए मिली न्यूनतम या अधिकतम आयु के साथ मेल खाए। फिर उससे कैसे निपटा जाए?
जूलियोमेक

2
यह काम नहीं करता है, यह अन्य क्षेत्रों द्वारा समूह है जो अवांछित है।
जैक कोल

1
@ जूलोमैक, मेरा मानना ​​है कि यदि आपका वांछित उत्पादन $ अधिकतम / $ मिनट है और उन फ़ील्ड्स को रखना जो $group_id में नहीं हैं , तो आप $sortवांछित क्षेत्र और फिर किसी भी क्षेत्र पर समूह $firstया उपयोग करने वाले $lastऑपरेटर के साथ पहले कर सकते हैं । संचय करते समय, अन्य क्षेत्रों (जो संचित / फ़नल / कम हो जाते हैं) को शामिल करने का विचार सैद्धांतिक रूप से भी बहुत अधिक मायने नहीं रखता है। हालांकि, हाथ से पहले छांटना वास्तव में अक्षम है क्योंकि प्रत्येक समूह को अपने आप में छांटना तुलनात्मक है क्योंकि छंटाई एल्गोरिदम ओ (एन) की तुलना में अधिक जटिल है। मेरी इच्छा है कि मोंगोडीबी में बेहतर तरीके हों।
वेमूलो

16

वैसे, यदि आप न केवल पहले दस्तावेज़ को रखना चाहते हैं, तो आप उदाहरण के लिए $ addToSet का उपयोग कर सकते हैं :

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

1
धन्यवाद! इसे बेहतर समझें (एक सेट के साथ आदेश को गड़बड़ाने से बचें): डेटा: {$ addToSet: {name: '$ name', _id: '$ _id', आयु: '$ युग'}}
बेनोइट

14

[टिप्पणी सुझावों को शामिल करने के लिए संपादित]

मैं यहाँ एक उत्तर की तलाश में आया था लेकिन चयनित उत्तर से खुश नहीं था (विशेषकर यह उम्र को देखते हुए)। मुझे यह उत्तर मिला कि एक बेहतर समाधान है (अनुकूलित):

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

3
लेकिन, आप countफ़ील्ड खो देते हैं । $mergeObjectsइसे रखने के लिए आपको उपयोग की आवश्यकता है।
0zkr PM

1
$ MergeObjects का उपयोग करने और सिंटैक्स के साथ दूसरों की मदद करने के बारे में 0zkr की टिप्पणी पर विस्तार करने के लिए, आखिरी पाइपलाइन सिंटैक्स होगा{"$replaceRoot": {"newRoot": {"$mergeObjects": ["$person", {count: "$count"}]}}}
जेरेन सॉन्डर्स

7

आप इसे आज़मा सकते हैं

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

}

4

यह मैंने क्या किया, यह ठीक काम करता है।

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

4

बस एक त्वरित अद्यतन अगर एक कई क्षेत्रों के साथ दस्तावेजों के साथ एक ही मुद्दे का सामना करता है। एक $replaceRootपाइपलाइन चरण और $mergeObjectsपाइपलाइन ऑपरेटर के संयोजन की शक्ति का उपयोग कर सकता है ।

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

4

दस्तावेज़ के $firstसाथ उपयोग करें $$ROOTऔर फिर $replaceRootपहले क्षेत्र के साथ उपयोग करें ।

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

यह कितना मददगार था! धन्यवाद!! मैं थोड़ी देर से खोज रहा था, लेकिन मुझे जो चाहिए था वह नहीं मिला। यह सही था!
द स्टूडेंट सोल

यह उत्तर 'टू द पॉइंट' और परफेक्ट है। धन्यवाद!
एम। नुनिसा

1

मुझे .groupहेल्पर के बारे में नहीं पता था , लेकिन अगर आप एग्रीगेशन फ्रेमवर्क के साथ जाना पसंद करते हैं , तो आपको होगा कि किस फील्ड में लौटना है। अगर मैं गलत हूं तो मुझे सुधारो, लेकिन SQL में तुम्हें वैसे भी करना होगा।

खैर, यह है कि आप इसे पहले उल्लेखित एग्रीगेशन फ्रेमवर्क के साथ कैसे करेंगे:

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

10
मदद के लिये शुक्रिया। इस क्वेरी में समूह निर्दिष्ट फ़ील्ड हैं, मैं केवल एक फ़ील्ड द्वारा समूह चाहता हूं, और फिर परिणाम अन्य फ़ील्ड निर्दिष्ट करते हैं। कोई अच्छा विचार?
प्लसर

1

मैंने इस समारोह को एक ख़त्म हुए मंच को सामान्य बनाने के लिए बनाया है ... मुझे बताएं कि क्या आप लोग इसके साथ किसी भी कीड़े के पार आते हैं, लेकिन यह मेरे लिए अच्छा काम कर रहा है!

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
}

एक ही जब एक ही संग्रह में दस्तावेज़ों में विभिन्न क्षेत्र का नाम होता है।
user7364588

0

यदि आप क्वेरी के नीचे सभी फ़ील्ड दस्तावेज़ का उपयोग करना चाहते हैं।

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

-1

यहाँ जवाब है >>>>

    $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();

कृपया अपनी इनपुट तालिका पहले सेट करें
पंकज चीमा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.