агрегат mongodb получает последний объект из вложенного документа, который выполняет запрос - PullRequest
1 голос
/ 03 июня 2019

В mongodb хранится следующий набор документов:

Запись разговора :

{_id: "x", lang: "en", timestamp: "", ... }

Каждый диалог имеет много процессов, каждый процесс имеет набор сообщенийкак список дочерних документов. Процесс запись:

{_id: "y", conversationId: "x", name: "", timestamp: "", messages: [
    {
        "direction" : "out",
        "text" : "How can I help you?",
        "timestamp" : ISODate("2019-05-23T11:08:18.423Z"),
        "_id" : 3
    },
    {
        "direction" : "out",
        "text" : "Hello",
        "timestamp" : ISODate("2019-05-23T11:08:17.423Z"),
        "_id" : 1
    },
    {
        "direction" : "in",
        "text" : "Hi",
        "timestamp" : ISODate("2019-05-23T11:08:18.423Z"),
        "_id" : 2
    }
], completed: "true"}

Мне нужно сделать запрос aggregate и получить список разговоров, в то время как каждый диалог должен иметь список процессов, упорядоченных по отметке времени, и каждый процесс должен иметьтолько последнее сообщение ( на основе поля идентификатора ) как изнутри, так и снаружи.

Нам нужно получить что-то вроде этого:

[
  {
    conversationId: "x",
    timestamp: "",
    processes: [
      {
        _id: "y",
        name: "",
        timestamp: "",
        lastInMessage: {
          "direction": "in",
          "text": "Hi",
          "timestamp": ISODate("2019-05-23T11:08:18.423Z"),
          "_id": 2
        },
        lastOutMessage: {
          "direction": "out",
          "text": "How can I help you?",
          "timestamp": ISODate("2019-05-23T11:08:18.423Z"),
          "_id": 3
        }
      },
      {
        _id: "y",
        name: "",
        ....
      }
    ]
  }
]

Я попробовал запрос:

conversation.aggregate([
        {
            $match: {
                timestamp: query.timestamp
            }
        },
        {
            $project: {
                _id: "$conversationId",
                timestamp: "$timestamp",
                conversationId: "$conversationId"
            }
        },
        {
            "$lookup":
                {
                    "from": "processes",
                    "localField": "conversationId",
                    "foreignField": "conversationId",
                    "as": "process"
                }
        },
        {
            $project: {
                _id: "$_id",
                timestamp: "$timestamp",
                // messages: "$process.messages",
                processes: "$process"
            }
        },
       // here I don't know what to do.

1 Ответ

1 голос
/ 03 июня 2019

Вы можете использовать $ redu * для вычисления минимального и максимального значения массива и использовать $ map для генерации агрегатов для всех process значений:

{
    $project: {
        _id: "$_id",
        timestamp: "$timestamp",
        processes: {
            $map: {
                input: "$processes",
                as: "process",
                in: {
                    _id: "$$process._id",
                    name: "$$process.name",
                    timestamp: "$$process.timestamp",
                    lastInMessage: {
                        $reduce: {
                            input: "$$process.messages",
                            initialValue: null,
                            in: {
                                $cond: [
                                    { $and: [ { $eq: [ "$$this.direction", "in" ] }, { $gt: [ "$$this.timestamp", "$$value.timestamp" ] } ] },
                                    "$$this",
                                    "$$value"
                                ]
                            }
                        }
                    },
                    lastOutMessage: {
                        $reduce: {
                            input: "$$process.messages",
                            initialValue: null,
                            in: {
                                $cond: [
                                    { $and: [ { $eq: [ "$$this.direction", "out" ] }, { $gt: [ "$$this.timestamp", "$$value.timestamp" ] } ] },
                                    "$$this",
                                    "$$value"
                                ]
                            }
                        }
                    }
                }
            }
        }
    }
}

Пример игровой площадки MongoDB

...