Найдите одну запись во вложенном массиве по идентификатору и отсортируйте на основе другого вложенного массива в MongoDB - PullRequest
1 голос
/ 05 мая 2020

У меня есть объект ниже в MongoDB, и моя серверная часть использует nodeJS. для получения данных из БД. оба "_id": "idq2" и "_id": "id1" даны нам в теле API.

questions = [
    {
        "_id": "idq1"
        "questiontext": "some question",
        "author": "auth2",
        "Answers": []
    },
    {
        "_id": "idq2"
        "questiontext": "some question",
        "author": "auth1",
        "Answers": [
            {
                "_id": "id1",
                "author": "auth1",
                "comments" [
                    {
                        "author": "auth1",
                        "comment": "some comments",
                        "rate": 1,
                        "_id": "idc1"
                    }
                    , {
                        "comment": "some comments",
                        "_id": "idc2"
                        "rate": 3
                    }
                    , {
                        "comment": "some comments",
                        "_id": "idc3"
                        "rate": 2
                    }
                    , {
                        "comment": "some comments",
                        "_id": "idc4",
                        "rate": 5
                    }
                ]

            },
            {
                "_id": "id2",
                "author": "auth2",
                "comments" []
            }
        ]
    }]

Предположим, у меня есть «_id»: «idq2» и «_id»: «id1», я пытаюсь получите объект ниже.

Ожидаемый результат:

Answer = {
    "_id": "id1",
    "author": "auth1",
    "comments" [
        {
            "author": "auth1",
            "comment": "some comments",
            "rate": 1,
            "_id": "idc1"
        },
        {
            "comment": "some comments",
            "_id": "idc3"
            "rate": 2
        }
        , {
            "comment": "some comments",
            "_id": "idc2"
            "rate": 3
        }

    ]
}

Чтобы сделать простой вопрос: как получить один объект «Ответы» с идентификатором «id1» и первые 3 комментария, отсортированных по параметру скорости в порядке возрастания, объект должен быть одним объектом.

1 Ответ

1 голос
/ 05 мая 2020

Вам нужно попробовать aggregation-pipeline для этого:

db.collection.aggregate([
    /** Filter docs with required criteria */
    {
      $match: { "_id": "idq2", "Answers._id": "id1" }
    },
    /** get only one needed element from `Answers` array & now `Answers` will be an object */
    {
      $project: {
        _id: 0,
        Answers: { $arrayElemAt: [ { $filter: { input: "$Answers", cond: { $eq: [ "$$this._id", "id1" ] } } }, 0 ] }
      }
    },
    /** Unwind `comments` array to do sorting */
    {
      $unwind: "$Answers.comments"
    },
    {
      $sort: {
        "Answers.comments.rate": 1
      }
    },
    /** group back based on `Answers._id` & push comments back to `comments` array */
    {
      $group: {
        _id: "$Answers._id",
        author: { $first: "$Answers.author" },
        comments: { $push: "$Answers.comments" }
      }
    }
  ])

Test: mongoplayground

Примечание: Этот запрос либо вернет пустой массив [], если ни один из документов не соответствует критериям $match, либо вернет массив из одного объекта в ответе. Помните, что .aggregate() всегда будет возвращать массив.

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