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

    {
    "_id" : ObjectId("592aa441e0f8de09b0912fe9"),
    "name" : "Patrick Rothfuss",
    "books" : [ 
    {
        "title" : "Name of the wind",
        "pages" : 400,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    }, 
    {
        "title" : "Wise Man's Fear",
        "pages" : 500,
        "_id" : ObjectId("592aa441e0f8de09b0912feb")
    },
    },
    {
    "_id" : ObjectId("592aa441e0f8de09b0912fe9"),
    "name" : "Rober Jordan",
    "books" : [ 
    {
        "title" : "The Eye of the World",
        "pages" : 400,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    }, 
    {
        "title" : "The Great Hunt",
        "pages" : 500,
        "_id" : ObjectId("592aa441e0f8de09b0912feb")
    }
    },

И я хотел бы запросить список всех книг во всей коллекции авторов - что-то вроде:

"books" : [ 
    {
        "title" : "The Eye of the World",
        "pages" : 400,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    }, 
    {
        "title" : "The Great Hunt",
        "pages" : 500,
        "_id" : ObjectId("592aa441e0f8de09b0912feb")
    },
    {
        "title" : "Name of the wind",
        "pages" : 400,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    },
    {
        "title" : "Wise Man's Fear",
        "pages" : 500,
        "_id" : ObjectId("592aa441e0f8de09b0912fea")
    }]
5
LadaWalker 28 Май 2017 в 13:57

2 ответа

Лучший ответ

Вы можете сделать это, используя .aggregate() и преимущественно $unwind оператор конвейера:

В современной MongoDB 3.4 и выше вы можете использовать их в тандеме с $replaceRoot

Model.aggregate([
  { "$unwind": "$books" },
  { "$replaceRoot": { "newRoot": "$books" } }
],function(err,results) {

})

В более ранних версиях вы указали все поля с помощью $project :

Model.aggregate([
  { "$unwind": "$books" },
  { "$project": {
    "_id": "$books._id",
    "pages": "$books.pages",
    "title": "$books.title"
  }}
],function(err,results) {

})

Итак, $unwind вы используете для деконструкции или «денормализовать» записи массива для обработки. Фактически это создает копию всего документа для каждого члена массива.

Остальная часть задачи заключается в возврате «только» тех полей, которые присутствуют в массиве.

Это не очень мудрая вещь, чтобы сделать все же. Если ваше намерение состоит в том, чтобы возвращать только контент, встроенный в массив документа, то лучше вместо этого поместить этот контент в отдельную коллекцию.

Это намного лучше для производительности, если отделить все документы из коллекции с помощью структуры агрегации, просто перечислив эти документы только из массива.

3
Neil Lunn 1 Июл 2017 в 05:28

В соответствии с приведенным выше описанием, попробуйте выполнить следующий запрос в оболочке MongoDB.

db.collection.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $unwind: "$books"
        },

        // Stage 2
        {
            $group: {
              _id:null,
              books:{$addToSet:'$books'}
            }
        },

        // Stage 3
        {
            $project: {
                books:1,
                _id:0
            }
        },

    ]

);
0
Rubin Porwal 29 Май 2017 в 06:06