Получить поле массива из нескольких документов и объединить элементы в один объект - PullRequest
0 голосов
/ 13 октября 2019

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

Получить 2 сообщения, начиная с индекса Nstart и заканчивая Nend от каждого пользователя в массиве имен пользователей: ['user1', 'user2'] и вернуть объединенный массив сообщений, упорядоченный попо возрастанию post.postedOn int.

Если это коллекция:

{
  username: "user1",
  posts: [
    { id: 1, text: "123" ... },
    { id: 2, text: "456" ... },
    { id: 3, text: "789" ... },
    ...
  ]
},
{
  username: "user2",
  posts: [
    { id: 1, text: "abc" ... },
    { id: 2, text: "def" ... },
    { id: 3, text: "ghi" ... },
    ...
  ]
}
...

Я хочу получить это:

{
  posts: {
    { id: 1, text: "123" ... },
    { id: 2, text: "456" ... },
    { id: 1, text: "abc" ... },
    { id: 2, text: "def" ... },
  }
}

Я пытался использовать aggregateмного раз. это один из моих запросов:

db.getCollection("users").aggregate([{ $match: { username: { $in: ["admin", "admin2"] } } }, { $project: { posts: 1 } }])

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

Окончательный результат I 'Я пытаюсь добиться этого:

Входные данные

  • Пользователи: ['user1', 'user2']
  • Начальный индекс сообщений: 4
  • Индекс конечных сообщений: 8

Результат

Массив сообщений выбранных пользователей. Общее количество 8 (ID 4-8 от каждого пользователя).

1 Ответ

0 голосов
/ 14 октября 2019

Для этого необходимо использовать операторы агрегирования $ slice и $ push , чтобы выбрать и добавить необходимые элементы записи (по индексу) в массив соответственно.

Например, в коллекции posts есть три документа (здесь я пропустил поле _id):

{
       "username" : "user2",
       "posts" : [
               {
                       "id" : 1,
                       "text" : "123"
               },
               {
                       "id" : 2,
                       "text" : "456"
               },
               {
                       "id" : 3,
                       "text" : "789"
               },
               {
                       "id" : 4,
                       "text" : "000"
               }
       ]
}
{
       "username" : "user1",
       "posts" : [
               {
                       "id" : 1,
                       "text" : "abc"
               },
               {
                       "id" : 2,
                       "text" : "def"
               },
               {
                       "id" : 3,
                       "text" : "ghi"
               },
               {
                       "id" : 4,
                       "text" : "zzz"
               }
       ]
}
{
        "username" : "user99",
        "posts" : [ ]
}

В оболочке Монго:

> var users = [ "user1", "user2" ]
> var startIx = 1, noOfElements = 2

> db.posts.aggregate([ 
  { $project: { _id: 0, username: 1, posts: 1, usersMatch: { $in: [ "$username",  users ] } } },
  { $match: { usersMatch: true } },
  { $addFields: { posts: { $slice: [ "$posts", startIx, noOfElements ] } } },
  { $group: { _id: null, postsOfSelectedUsers: { $push: "$posts"} } },
  { $project: { _id: 0, selectedUsers: users, postsOfSelectedUsers: 1 } } 
])

Выход:

{
        "postsOfSelectedUsers" : [
                [
                        {
                                "id" : 2,
                                "text" : "456"
                        },
                        {
                                "id" : 3,
                                "text" : "789"
                        }
                ],
                [
                        {
                                "id" : 2,
                                "text" : "def"
                        },
                        {
                                "id" : 3,
                                "text" : "ghi"
                        }
                ]
        ],
        "selectedUsers" : [
                "user1",
                "user2"
        ]
}

ПРИМЕЧАНИЕ : Это решение, но его можно улучшить или переработать (Iдумаю).

...