【问题标题】:mongoDB query for retrieving from nested array collection用于从嵌套数组集合中检索的 mongoDB 查询
【发布时间】:2016-06-15 13:28:29
【问题描述】:
{
    "_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
}

这是我的 json 结构。我想要一个 mongoDB 查询来检索今天登录的每个用户,即其Last_Login 具有今天的日期。

我希望我的输出为:

{
    "_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
}

【问题讨论】:

  • 这样存储的日期将需要可能无效的复杂查询。考虑将架构更改为将 Last_Login 日期存储为 ISODate()
  • Last_Login 字段包含 moment().format('llll') 格式的数据,由 moment.js 库提供,我还需要将其更改为 ISODate() 吗???
  • 是的,最好将 MongoDB 中的日期存储为适当的 Date() 类型,而不是将它们存储为上述格式的字符串。
  • 你能给我一个将它作为 ISODate() 插入的例子吗,现在我将它用作: Last_Login : moment.format('llll')
  • moment() 有一个 toDate() 方法,您可以使用它返回一个 JavaScript Date 对象或简单地创建一个 JS Date 对象的新实例。所以你可以像 Last_Login: moment().toDate()Last_Login: new Date() 那样做

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

您将需要$elemMatchaggregate

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

所以查询将执行这些步骤:

  1. $unwind 所有Sessions 元素
  2. $match 日期范围内的文档
  3. $group_idFirst_NameLast_Name 共同提供文件
  4. $project 文件看起来像原始格式

我省略了一些字段,但您可以轻松地将其添加到$group$project 步骤中。当然,您需要更改日期范围。

我担心此查询在大型集合中的性能。如果您使用我给出的第一个查询并在代码中过滤您想要的会话,也许会更好。

编辑:

正如@chridam 所说,此查询仅在您将Last_Login 更改为ISODate() 时才有效,这是推荐的。

编辑 2:

更新查询以使用aggregate 并匹配在日期范围内仅获取Sessions 的请求。

这是旧版本:

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

【讨论】:

  • 不太确定查询是否会工作,因为Last_Login 日期由 OP 作为字符串给出。
  • @chridam 当然,我没注意到。
  • 它说 ISODate() 未定义...其他替代方案??
  • ok.. 使用 Date() 完成了它,但我没有得到预期的输出。它输出匹配对象内的所有数据,甚至是昨天的登录时间
  • 所以你只想返回最后一次登录会话?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-29
  • 2018-09-10
  • 1970-01-01
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多