У меня есть образец документа, который я пытаюсь выполнить в рамках агрегатного конвейера 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
но мне хотелось попробовать немного сжаться/очистить ее.
Вам действительно нужно использовать $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
которая невозможна, и вы можете только реально обозначить массив "весь". На самом деле это не то, что вы хотите проверить здесь.
$map
но вполне понятно, что он подходит для использования, когда вы думаете об этом. Я думаю, что документы просто привели меня на неверный путь, поскольку казалось, что я должен быть в состоянии сделать то, что я хотел.