Примените выражение к каждому элементу массива в документе

1

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

{
    "_id" : "",
    "title" : "Questions",
    "sortIndex" : 0,
    "topics" : [ 
        {
            "_id" : "",
            "title" : "Creating a Question",
            "sortIndex" : 1,
            "thumbnail" : "CreatingAQuestion.jpg",
            "seenBy" : [ "user101", "user202" ],
            "pages" : [ 
                {
                    "visual" : "SelectPlanets.gif",
                    "text" : "Some Markdown"
                }
            ]
        }, 
        {
            "_id" : "",
            "title" : "Deleting a Question",
            "sortIndex" : 0,
            "thumbnail" : "DeletingAQuestion.jpg",
            "seenBy" : [ "user101" ],
            "pages" : [ 
                {
                    "visual" : "SelectCard.gif",
                    "text" : "Some Markdown"
                }
            ]
        }
    ]
}

Результат, который я пытаюсь получить, - это что-то в этом роде:

{
    "_id" : "",
    "title" : "Questions",
    "topics" : [ 
        {
            "title" : "Creating a Question",
            "thumbnail" : "CreatingAQuestion.jpg",
            "seen" : true
        }, 
        {
            "title" : "Deleting a Question",
            "thumbnail" : "DeletingAQuestion.jpg",
            "seen" : false
        }
    ]
}

В частности, бит, с которым я борюсь, - это seen флаг.

Я прочитал документы, в которых говорится:

При проектировании или добавлении/сбросе поля внутри встроенного документа...

... Или вы можете вложить поля:

contact: { address: { country: <1 or 0 or expression> } }

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

При вложенности полей вы не можете использовать точечную нотацию внутри встроенного документа для указания поля, например, контакт: { "address.country": <1 or 0 or expression> } является недопустимым.

Поэтому я пытаюсь понять, как "ссылаться" на поле поддокумента внутри выражения. Эта цитата предполагает, что я не могу использовать точечную нотацию, но когда я не могу заставить ее работать с вложенными обозначениями. Вот что у меня есть до сих пор:

db
    .getCollection('chapters')
    .aggregate([
        {
            $project: {
                title: 1,
                topics: {
                    title: 1,
                    thumbnail: 1,
                    publishedAt: 1,
                    test: "$seenBy",
                    seen: { $in: ["user202", "$seenBy"] },
                }
            }
        }
    ])

Таким образом, я уже запрограммировал user202 в моем запросе и ожидал увидеть true и false для двух документов. Я также поставил test поле для отображения поля seenBy из seenBy. Что это производит:

{
    "_id" : "",
    "title" : "Questions",
    "topics" : [ 
        {
            "title" : "Creating a Question",
            "thumbnail" : "CreatingAQuestion.jpg",
            "test" : [ 
                "user101", 
                "user202"
            ],
            "seen" : true
        }, 
        {
            "title" : "Deleting a Question",
            "thumbnail" : "DeletingAQuestion.jpg",
            "test" : [ 
                "user101", 
                "user202"
            ],
            "seen" : true
        }
    ]
}

Таким образом, очевидно, что мой "$ seenBy" не имеет доступа к правильной теме, потому что поле test содержит данные из 1-го документа.

Итак, в конечном счете, мой вопрос заключается в том, как я могу получить доступ к полю seenBy внутри поддокумента, ссылаясь на текущий поддокумент, чтобы я мог создать выражение?

Примечание. У меня есть работа с несколькими $project и $unwind но мне хотелось попробовать немного сжаться/очистить ее.

Теги:
aggregation-framework

1 ответ

2
Лучший ответ

Вам действительно нужно использовать $map здесь. Простое обозначение массива в проекции (это немного благо, так как MongoDB 3.2) на самом деле не режет его, когда вам нужно локализованное значение для текущего элемента. Это то, что вам нужно, и то, что предоставляет $map:

db.getCollection('chapters').aggregate([
   { $project: {
     title: 1,
     topics: {
       $map: {
         input: "$topics",
         as: "t",
         in: {
           title: "$$t.title",
           thumbnail: "$$t.thumbnail",
           publishedAt: "$$t.publishedAt",
           test: "$$t.seenBy",
           seen: { $in: ["user202", "$$t.seenBy"] },
        }
      }
   }}
])

Таким образом, для каждого элемента текущее значение "seenBy" как свойство тестируется выражением. Без $map которая невозможна, и вы можете только реально обозначить массив "весь". На самом деле это не то, что вы хотите проверить здесь.

  • 0
    Это большое спасибо, раньше я не использовал $map но вполне понятно, что он подходит для использования, когда вы думаете об этом. Я думаю, что документы просто привели меня на неверный путь, поскольку казалось, что я должен быть в состоянии сделать то, что я хотел.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню