LoginSignup
7
6

More than 5 years have passed since last update.

MongoDB aggregateion 簡単サンプルコマンド & Mongoose#Aggregate() by node.js

Last updated at Posted at 2016-12-28

▪️今日のお悩み

  • MongoDBで、groupbyとかdistinctとかどうするの?
  • それをnode.jsで実装する場合はどうするの?

▪️解決

  • MongoDBのaggregateを使う。
  • node.jsでMongoDBを使う時は、monngooseを使う。

> まずは参考となるリンク集

こちらを読んでいき、実際にデータをフィルタさせていくと、なんとなくコツがつかめてきます。

> MongoDBでaggregationする簡単なサンプル

> aggregationするデータの準備

  • ちなみに、MongoDBでの日付の挿入は以下の通り
db.example.insert({"date":new Date(Date.now())});
  • monngooseは、collectionを複数形で作成する必要があります。

後で出てきますが、以下のようにTopicモデルを作成すると、
MongoDB側のターゲットが「topic」かと思いきや「topics」になっているので、よくはまるので気をつけてください。

var TopicModel = mongoose.model('Topic', topicSchema);
  • サンプルデータをinsertします

db.topics.insert(
[
   {
      posted_at: new Date(Date.now()),
      posted_by: 'tanaka',
      data: 'hogehoge',
      room:'room_1',
      topic_text:'Todays Weather',
   },
   {
      posted_at: new Date(Date.now()),
      posted_by: 'okamoto',
      data: 'hogehoge',
      room:'room_2',
      topic_text:'Todays Weather',
   },
   {
      posted_at: new Date(Date.now()),
      posted_by: 'tanaka',
      data: 'hogehoge',
      room:'room_2',
      topic_text:'Todays Weather',
   },
   {
      posted_at: new Date(Date.now()),
      posted_by: 'yamamoto',
      data: 'hogehoge',
      room:'room_1',
      topic_text:'New Year',
   },
   {
      posted_at: new Date(Date.now()),
      posted_by: 'tanaka',
      data: 'hogehoge',
      room:'room_1',
      topic_text:'Count Down',
   },
]
)
  • データをselectします
    • prettyをつけてあげると、分かりやすいJSON形式で出力してくれます。 db.topics.find().pretty()

> Aggregationの実行

Aggregationは、unixのpipe "|" operatorに似ています。

  • count
    • posted_by毎の数
db.topics.aggregate([
{$group : {_id : "$posted_by", num : {$sum : 1}}}
])


{ "_id" : "yamamoto", "num" : 1 }
{ "_id" : "okamoto", "num" : 1 }
{ "_id" : "tanaka", "num" : 3 }
  • group
    • room毎にgroupby

db.topics.aggregate( [ 
{ $group : { _id :  { room: "$room" },  profile: { $push: "$$ROOT" }} } 
] ).pretty()



{
    "_id" : {
        "room" : "room_2"
    },
    "profile" : [
        {
            "_id" : ObjectId("5861f90669e5e0b2eb21f16c"),
            "posted_at" : ISODate("2016-12-27T05:15:50.603Z"),
            "posted_by" : "okamoto",
            "data" : "hogehoge",
            "room" : "room_2",
            "topic_text" : "Todays Weather"
        },
        {
            "_id" : ObjectId("5861f90669e5e0b2eb21f16d"),
            "posted_at" : ISODate("2016-12-27T05:15:50.603Z"),
            "posted_by" : "tanaka",
            "data" : "hogehoge",
            "room" : "room_2",
            "topic_text" : "Todays Weather"
        }
    ]
}
{
    "_id" : {
        "room" : "room_1"
    },
    "profile" : [
        {
            "_id" : ObjectId("5861f90669e5e0b2eb21f16b"),
            "posted_at" : ISODate("2016-12-27T05:15:50.603Z"),
            "posted_by" : "tanaka",
            "data" : "hogehoge",
            "room" : "room_1",
            "topic_text" : "Todays Weather"
        },
        {
            "_id" : ObjectId("5861f90669e5e0b2eb21f16e"),
            "posted_at" : ISODate("2016-12-27T05:15:50.603Z"),
            "posted_by" : "yamamoto",
            "data" : "hogehoge",
            "room" : "room_1",
            "topic_text" : "New Year"
        },
        {
            "_id" : ObjectId("5861f90669e5e0b2eb21f16f"),
            "posted_at" : ISODate("2016-12-27T05:15:50.603Z"),
            "posted_by" : "tanaka",
            "data" : "hogehoge",
            "room" : "room_1",
            "topic_text" : "Count Down"
        }
    ]
}

  • match+ group + sort
    • room = room_1
    • posted_atのソート
    • topic_text毎
db.topics.aggregate( [ 
{ $match: { room : "room_1"}},
{ $sort: {posted_at:1}},
{ $group : { _id :  { topic_text: "$topic_text" },  profile: { $push: "$$ROOT" }} } 
] ).pretty()

{
    "_id" : {
        "topic_text" : "Count Down"
    },
    "profile" : [
        {
            "_id" : ObjectId("5861f90669e5e0b2eb21f16f"),
            "posted_at" : ISODate("2016-12-27T05:15:50.603Z"),
            "posted_by" : "tanaka",
            "data" : "hogehoge",
            "room" : "room_1",
            "topic_text" : "Count Down"
        }
    ]
}
{
    "_id" : {
        "topic_text" : "New Year"
    },
    "profile" : [
        {
            "_id" : ObjectId("5861f90669e5e0b2eb21f16e"),
            "posted_at" : ISODate("2016-12-27T05:15:50.603Z"),
            "posted_by" : "yamamoto",
            "data" : "hogehoge",
            "room" : "room_1",
            "topic_text" : "New Year"
        }
    ]
}
{
    "_id" : {
        "topic_text" : "Todays Weather"
    },
    "profile" : [
        {
            "_id" : ObjectId("5861f90669e5e0b2eb21f16b"),
            "posted_at" : ISODate("2016-12-27T05:15:50.603Z"),
            "posted_by" : "tanaka",
            "data" : "hogehoge",
            "room" : "room_1",
            "topic_text" : "Todays Weather"
        }
    ]
}

> monngoose+ node.jsでの実装

さて、上記のaggregateで実行したものをnode.jsで書きます。
npm install で mongoose をインストールして使います。


var mongoose = require('mongoose');
var Schema = mongoose.Schema;

//Database connection
var uristring = 'mongodb://localhost/jp';
var mongoOptions = { };

mongoose.connect(uristring, mongoOptions, function (err, res) {
    if (err) {
        console.log('Error when connecting to: ' + uristring + '. ' + err);
    }
    else {
        console.log('Successfully connected to: ' + uristring);
    }
});


//Schemas:

var topicSchema = new Schema({
    posted_by: {
        type: String,
        default: ''
    },
    posted_at: {
        type: Date,
        default: Date.now
    },
    data: {
        type: String,
        default: JSON.stringify({})
    },
    room: {
        type: String,
        default: ''
    },
    topic_text: {
        type: String,
        default: ''
    }
});


//Define Models
var TopicModel = mongoose.model('Topic', topicSchema);


getTopicProfile("room_1", function(err, data){
    if(!err){
        console.log(JSON.stringify(data));
    }
});


//Aggregation function
function getTopicProfile(room_name, callback) {
    TopicModel.aggregate([
        { $match: {
            room: room_name
        }},
        { $sort: {posted_at:1}},
        { $group: {
            _id :  {  topic_text: "$topic_text" },
            profile: { $push: "$$ROOT" }
            }
        }
    ], function (err, result) {
        if (err) {
            console.log(err);
            return;
        }
        console.log(JSON.stringify(result));
    });
}
7
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6