mongoDB query for retrieving from nested array collection

被刻印的时光 ゝ 提交于 2019-12-23 13:28:33

问题


{
    "_id" : ObjectId("576155a6cd87b68f7e6e42c9"),
    "First_Name" : "ok",
    "Last_Name" : "jaao",
    "Email" : "xyz@gmail.com",
    "Sessions" : [
        {
            "Last_Login" : "Wed, Jun 14, 2016 6:48 PM",
            "Class" : "fb",
            "ID" : "123"
        },
        {
            "Last_Login" : "Wed, Jun 15, 2016 6:48 PM",
            "ID" : "111",
            "Class" : "fb"
        }
    ],
    "Count" : 2
},
{
    "_id" : ObjectId("576155ccf6d8979e7e77df27"),
    "First_Name" : "abc",
    "Last_Name" : "xyz",
    "Email" : "xyz@gmail.com",
    "Sessions" : [
        {
            "Last_Login" : "Wed, Jun 15, 2016 6:49 PM",
            "Class" : "fb",
            "ID" : "123"
        }
    ],
    "Count" : 1
}

This is my json structure. and I want a mongoDB query which retrieves every user that has logged in today i.e., whose Last_Login has today's date.

I want my output as:

{
    "_id" : ObjectId("576155a6cd87b68f7e6e42c9"),
    "First_Name" : "ok",
    "Last_Name" : "jaao",
    "Email" : "xyz@gmail.com",
    "Sessions" : [
        {
            "Last_Login" : "Wed, Jun 15, 2016 6:48 PM",
            "ID" : "111",
            "Class" : "fb"
        }
    ],
    "Count" : 2
},
{
    "_id" : ObjectId("576155ccf6d8979e7e77df27"),
    "First_Name" : "abc",
    "Last_Name" : "xyz",
    "Email" : "xyz@gmail.com",
    "Sessions" : [
        {
            "Last_Login" : "Wed, Jun 15, 2016 6:49 PM",
            "Class" : "fb",
            "ID" : "123"
        }
    ],
    "Count" : 1
}

回答1:


You will need $elemMatch and aggregate.

db.users.aggregate([
    {
        $unwind: "$Sessions"
    },
    {
        $match: {
            "Sessions.Last_Login": {
                $gte: ISODate("2016-06-16T00:00:00.0Z"),
                $lt: ISODate("2016-06-17T00:00:00.0Z")
            }
        }
    },
    {
        $group: {
            _id: {
                _id: "$_id",
                First_Name: "$First_Name",
                Last_Name: "$Last_Name"
            },
            Sessions: {
                $push: "$Sessions"
            }
        }
    },
    {
        $project: {
            _id: "$_id._id",
            First_Name: "$_id.First_Name",
            Last_Name: "$_id.Last_Name",
            Sessions: "$Sessions"
        }
    }
])

So the query will do those steps:

  1. $unwind all Sessions elements
  2. $match documents inside the date range
  3. $group together documents by _id, First_Name, Last_Name
  4. $project documents to look like the original format

I omitted some fields, but you can easily add it in $group and $project steps. And of course you'll need to change the date range.

I'm concerned about the performance of this query in a big collection. Maybe is better if you use the first query I gave and filter the sessions you want in your code.

Edit:

As @chridam said, this query will work only if you change Last_Login to ISODate(), what is recommended.

Edit 2:

Updating the query to use aggregate and match the request of only fetch Sessions inside the date range.

This is the old version:

db.users.filter({
    'Sessions': {
        '$elemMatch': {
            'Last_Login': {
                '$gte': ISODate("2016-06-16T00:00:00.0Z"),
                '$lt': ISODate("2016-06-17T00:00:00.0Z")
            }
        }
    }
})


来源:https://stackoverflow.com/questions/37836891/mongodb-query-for-retrieving-from-nested-array-collection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!