MongoDB检索与聚合字段对应的子级文档值

时间:2015-11-06 08:39:04

标签: mongodb mongodb-query

我有一个具有以下结构的mongodb集合。

/* 0 */
{
  "_id" : ObjectId("5633cc4fd6f8ebfddf32fa77"),
  "contact_name" : "Fred Flintstone",
  "follow_up_date" : ISODate("2015-11-02T20:02:58.766Z"),
  "notes" : [
        {
            "author" : "Miles",
      "note_date" : ISODate("2015-10-30T20:00:15.735Z"),
      "note_text" : "Appointment requested via web interface",
      "source_type" : "appointment_request"
        },
        {
            "author" : "John",
      "note_date" : ISODate("2015-10-20T18:00:15.735Z"),
      "note_text" : "Phone support ticket",
      "source_type" : "web_support"
        }
    ]
}

/* 1 */
{
  "_id" : ObjectId("56381fe8d6f8ebfddf32fb8c"),
  "contact_name" : "Barney Rubble",
  "follow_up_date" : ISODate("2015-10-14T20:02:58.766Z"),
  "notes" : [
        {
            "author" : "John",
      "note_date" : ISODate("2015-10-30T20:00:15.735Z"),
      "note_text" : "Note entered",
      "source_type" : "note"
        },
        {
            "author" : "John",
      "note_date" : ISODate("2015-10-11T16:00:15.735Z"),
      "note_text" : "Account created",
      "source_type" : "account_activity"
        }
    ]
}

我想构建一个聚合查询,以便检索contact_name,follow_up_date,最大notes.note_date以及相应的notes.note_text和notes.source_type值。这可以通过一次“聚合”调用来实现吗?到目前为止,我的聚合管道集如下:

[
    {
        $unwind: "$notes"
    },
    {
        $group: {
            _id: { 
                lead_id: "$_id", 
                contact_name: "$contact_name", 
                follow_up_date: "$follow_up_date" 
            },
            "num_entries": { "$sum": 1 },
            "last_entry": { "$max": "$notes.note_date" }
        }
    },
    {
        $project: {
            "contact_name": "$_id.contact_name",
            "follow_up_date": "$_id.follow_up_date",
            "last_entry": "$last_entry",
            "num_entries": "$num_entries",
            "lead_id": "$_id.lead_id"
        }
    }
]

除了note_text和source_type以及“last_entry”:{“$ max”:“$ notes.note_date”}值之外,这将获得我需要的一切。这是目前返回的内容:

[
    {
        "_id": {
            "lead_id": "563c69a4d6f8ebfddf32fce0",
            "contact_name": "Barney Rubble",
            "follow_up_date": "2015-10-14T20:02:58.766Z"
        },
        "num_entries": 2,
        "last_entry": "2015-10-30T20:00:15.735Z",
        "contact_name": "Barney Rubble",
        "follow_up_date": "2015-10-14T20:02:58.766Z",
        "lead_id": "563c69a4d6f8ebfddf32fce0"
    },
    {
        "_id": {
            "lead_id": "563c698fd6f8ebfddf32fcdf",
            "contact_name": "Fred Flintstone",
            "follow_up_date": "2015-11-02T20:02:58.766Z"
        },
        "num_entries": 2,
        "last_entry": "2015-10-30T20:00:15.735Z",
        "contact_name": "Fred Flintstone",
        "follow_up_date": "2015-11-02T20:02:58.766Z",
        "lead_id": "563c698fd6f8ebfddf32fcdf"
    }
]

这就是我需要的:

[
    {
        "_id": {
            "lead_id": "563c69a4d6f8ebfddf32fce0",
            "contact_name": "Barney Rubble",
            "follow_up_date": "2015-10-14T20:02:58.766Z"
        },
        "num_entries": 2,
        "last_entry": "2015-10-30T20:00:15.735Z",
        "last_entry_source_type": "appointment_request",
        "last_entry_note_text": "Appointment requested via web interface",
        "contact_name": "Barney Rubble",
        "follow_up_date": "2015-10-14T20:02:58.766Z",
        "lead_id": "563c69a4d6f8ebfddf32fce0"
    },
    {
        "_id": {
            "lead_id": "563c698fd6f8ebfddf32fcdf",
            "contact_name": "Fred Flintstone",
            "follow_up_date": "2015-11-02T20:02:58.766Z"
        },
        "num_entries": 2,
        "last_entry": "2015-10-30T20:00:15.735Z",
        "last_entry_source_type": "note",
        "last_entry_note_text": "Note entered",
        "contact_name": "Fred Flintstone",
        "follow_up_date": "2015-11-02T20:02:58.766Z",
        "lead_id": "563c698fd6f8ebfddf32fcdf"
    }
]

1 个答案:

答案 0 :(得分:1)

$sort 管道之前引入 $group 管道步骤,以便通过note_date键对文档流进行重新排序然后,您可以应用组累加器运算符 $first $last ,这些只有在文档按定义的顺序时才有意义。运算符将允许您提取整个非规范化notes文档,然后 $project 阶段将进行一些字段重新整形。

最终的聚合管道如下所示:

[
    {
        "$unwind": "$notes"
    },
    { 
        "$sort": { "notes.note_date": 1 } 
    },
    {
        "$group": {
            "_id": { 
                "lead_id": "$_id", 
                "contact_name": "$contact_name", 
                "follow_up_date": "$follow_up_date" 
            },
            "num_entries": { "$sum": 1 },
            "last_entry": { "$last": "$notes" }
        }
    },
    {
        "$project": {
            "contact_name": "$_id.contact_name",
            "follow_up_date": "$_id.follow_up_date",
            "last_entry": "$last_entry.note_date",
            "last_entry_source_type": "$last_entry.source_type",
            "last_entry_note_text": "$last_entry.note_text",
            "num_entries": 1,
            "lead_id": "$_id.lead_id"
        }
    }
]