Подзапрос в MongoDB для возврата одного элемента с определенным полем - PullRequest
0 голосов
/ 04 октября 2019

У меня есть две коллекции, где одна имеет массив с идентификаторами другой. Мне нужно вернуть элемент из первой коллекции и элемент из второй коллекции, но только элемент, который имеет определенное поле. Я уточню.

Я пытался что-то сделать, используя это, но не мог полностью понять операцию. https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/

Мой вопрос:

{
  "solved": false,
  "answer": [
     "5d969dbf7d496a256443eeca",
     "5d969f7b7d496a256443eecb"
  ],
  "_id": "5d93dfaf40024619dcc61896",
  "user": "5d8963afa0014a289c8d7112",
  "title": "Ola mundo",
  "description": "esse e um teste",
  "discipline": "5d8fb8e04becf712f8293b5b",
  "createdAt": "2019-10-01T23:22:23.168Z",
  "__v": 0
},

Мои Awnsers

{
  "official": false,
  "_id": "5d969dbf7d496a256443eeca",
  "description": "Toma aqui a sua resposta",
  "createdAt": "2019-10-04T01:17:51.454Z",
  "__v": 0
},
{
  "official": true,
  "_id": "5d969f7b7d496a256443eecb",
  "description": "Esste e um teeeeste",
  "createdAt": "2019-10-04T01:25:15.829Z",
  "__v": 0
}

Мне нужно вернуть модель вопроса и модель Awnser, где "официальный""поле равно" истина ". Я новичок в mongoDB, поэтому я прошу помощи. Я думал, что может быть что-то вроде подзапроса в sql.

Ответы [ 2 ]

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

Похоже, вы уже используете mongoose, поэтому вы можете использовать , чтобы заполнить условие запроса , чтобы решить вашу проблему. Что-то вроде:

Question.find(...).populate({
  path: 'answer',
  match: { official: true}
})
0 голосов
/ 04 октября 2019

Самый простой способ - использовать агрегацию.

Вам необходимо объединить все идентификаторы из массива ответов в коллекцию ответов, используя $ lookup, а затем использовать $ filter, чтобы отфильтровать его по «официальным».

объедините документы из коллекции Ответов, если _ids совпадают

{
    $lookup: {
        from: "Answer",
        foreignField: "_id",
        localField: "answer",
        as: "answer"
    }

}

Результат будет:

{
    "_id" : ObjectId("5d93dfaf40024619dcc61896"),
    "solved" : false,
    "answer" : [
        {
            "_id" : ObjectId("5d969dbf7d496a256443eeca"),
            "official" : false,
            "description" : "Toma aqui a sua resposta",
            "createdAt" : "2019-10-04T01:17:51.454Z",
            "__v" : 0
        },
        {
            "_id" : ObjectId("5d969f7b7d496a256443eecb"),
            "official" : true,
            "description" : "Esste e um teeeeste",
            "createdAt" : "2019-10-04T01:25:15.829Z",
            "__v" : 0
        }
    ],
    "user" : "5d8963afa0014a289c8d7112",
    "title" : "Ola mundo",
    "description" : "esse e um teste",
    "discipline" : "5d8fb8e04becf712f8293b5b",
    "createdAt" : "2019-10-01T23:22:23.168Z",
    "__v" : 0
}

Теперь, когда вы присоединились к документам, вы можете отфильтровать его по "официальное »поле с использованием $ addFields и $ filter. $ addFields добавляет новые поля в документ https://docs.mongodb.com/manual/reference/operator/aggregation/addFields/. В этом решении я использую то же имя поля «answer», оно перезапишет массив ответов с отфильтрованными документами.

{
    $addFields: {
        answer: {
            $filter: {
                input: "$answer",
                as: "answer",
                cond: { $eq: [ "$$answer.official", true ] }
            }
        }

    }
}

Результатбудет:

{
    "_id" : ObjectId("5d93dfaf40024619dcc61896"),
    "solved" : false,
    "answer" : [
        {
            "_id" : ObjectId("5d969f7b7d496a256443eecb"),
            "official" : true,
            "description" : "Esste e um teeeeste",
            "createdAt" : "2019-10-04T01:25:15.829Z",
            "__v" : 0
        }
    ],
    "user" : "5d8963afa0014a289c8d7112",
    "title" : "Ola mundo",
    "description" : "esse e um teste",
    "discipline" : "5d8fb8e04becf712f8293b5b",
    "createdAt" : "2019-10-01T23:22:23.168Z",
    "__v" : 0
}

Это полный запрос:

db.Question.aggregate([
{
    $lookup: {
        from: "Answer",
        foreignField: "_id",
        localField: "answer",
        as: "answer"
    }

},
{
    $addFields: {
        answer: {
            $filter: {
                input: "$answer",
                as: "answer",
                cond: { $eq: [ "$$answer.official", true ] }
            }
        }

    }
}])
...