Запрос из двух коллекций в MongoDB - PullRequest
1 голос
/ 05 февраля 2020

Я пытаюсь найти способ обойти MongoDB. Я впервые использую эту базу данных, начиная с MySQL. Но для приложения чата, которое я создаю, MongoDB рекомендовано как более подходящее.

У меня есть две коллекции:

разговоров , в которых я храню ID пользователя ( который хранится в базе данных MySQL) и дате присоединения.

{
    "_id" : ObjectId("5e35f2c840713a43aeeeb3d9"),
    "members" : [ 
        {
            "uID" : "1",
            "j" : 1580580922
        }, 
        {
            "uID" : "4",
            "j" : 1580580922
        }, 
        {
            "uID" : "5",
            "j" : 1580580922
        }
    ]
}

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

{
    "_id" : ObjectId("5e35ee5f40713a43aeeeb1c5"),
    "c_ID" : ObjectId("5e35f2c840713a43aeeeb3d9"),
    "fromID" : "1",
    "msg" : "What's up?",
    "t" : 1580591922,
    "d" : {
        "4" : 1580592039
    },
    "r" : {
        "4" : 1580592339
    }
}

Теперь я хочу запросить разговоры для определенного пользователя c, скажем, userID 1, вместе с последним сообщением, отправленным в этом разговоре.

Я придумал следующее:

db.getCollection('conversations').aggregate(
[{
    $match: {
        "members.uID": "1"
    }
},
{
    $lookup: {
        as: 'lastMessage',
        foreignField: 'c_ID',
        from: 'messages',
        localField: '_id',
    }
},
])

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

Любая помощь приветствуется!

1 Ответ

1 голос
/ 05 февраля 2020

Я думаю, мы можем понять последнее сообщение из поля отметки времени.

После этапов $match и $lookup нам нужно $ развернуть сообщений, а затем $ sort by timestamp.

Теперь первое сообщение в массиве сообщений - это lastMessage, поэтому, когда мы group , мы выводим sh первое сообщение как lastMessage и, наконец, $ replace Root для формирования нашего результата.

Если это возможно, вы можете использовать следующую агрегацию:

db.conversations.aggregate([
  {
    $match: {
      "members.uID": "1"
    }
  },
  {
    $lookup: {
      foreignField: "c_ID",
      from: "messages",
      localField: "_id",
      as: "messages"
    }
  },
  {
    "$unwind": "$messages"
  },
  {
    "$sort": {
      "messages.t": -1
    }
  },
  {
    "$group": {
      "_id": "$_id",
      "lastMessage": {
        "$first": "$messages"
      },
      "allFields": {
        "$first": "$$ROOT"
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          "$allFields",
          {
            "lastMessage": "$lastMessage"
          }
        ]
      }
    }
  },
  {
    $project: {
      messages: 0
    }
  }
])

Если массив сообщений уже отсортирован, решение можно упростить, но это общее решение.

Детская площадка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...