#mongodb #aggregation-framework
Вопрос:
Я изо всех сил пытаюсь создать запрос MongoDB для использования агрегации для выполнения соединения, подобного запросу с условиями. Это мой вклад :
Коллекция «Вещи» :
{
_id : 1
users : [
{
userId : 00001,
role : "creator"
},
{
userId : 00002,
role : "spectator"
}
]
}
{
_id : 2
users : [
{
userId : 00002,
role : "creator"
},
{
userId : 00001,
role : "spectator"
}
]
}
Коллекция «Пользователи» :
{
_id : 00001,
name : "John"
}
{
_id : 00002,
name : "Doe"
}
Я хочу получить имя/информацию создателя для данной «Вещи» _id и получить что-то подобное для _id = 1:
{
_id : 00001,
name : "John"
}
Вот где я был до сих пор :
db.Things.aggregate([
{
$match:{
_id:1
}
},
{
$lookup:{
from:"Users",
localField:"Users.userId",
foreignField:"_id",
as:"usersData"
}
},
{
$unwind : "$usersData"
}
])
Заранее спасибо.
Комментарии:
1. есть также
userId : 00002
в_id = 1
, можете ли вы показать свой ожидаемый результат.2.
userId : 00002
у in_id = 1
нет ролиcreator
» ноspectator
«в массиве «пользователи», поэтому он не является частью ожидаемого результата3. это возможно, если есть 2 совпадающих использования из массива пользователей? если да, то как вы хотите получить результат, в отдельном документе или в том же документе.
4. Это невозможно. У каждого
thing
есть только одинcreator
, и было бы идеально, если бы у меня было только имя создателя,_id
но пока у меня естьname
это нормально
Ответ №1:
$match
вещи_id
иrole
состояние пользователей$unwind
деконструироватьusers
массив$match
users
условие роли$lookup
сusers
коллекцией$arrayElemAt
чтобы получить первый элемент из результата поиска$replaceRoot
чтобы заменить указанный выше объект на корневой
db.things.aggregate([
{ $match: { _id: 1, "users.role": "creator" } },
{ $unwind: "$users" },
{ $match: { "users.role": "creator" } },
{
$lookup: {
from: "Users",
localField: "users.userId",
foreignField: "_id",
as: "users"
}
},
{
$replaceRoot: {
newRoot: { $arrayElemAt: ["$users", 0] }
}
}
])
Второй подход без использования $undind
этапа,
$match
вещи_id
иrole
состояние пользователей$filter
для повторения циклаuses
массива и фильтрации поrole
создателю$arrayElemAt
чтобы выбрать первый элемент из приведенного выше отфильтрованного результата$lookup
сusers
коллекцией$arrayElemAt
чтобы получить первый элемент из результата поиска$replaceRoot
чтобы заменить указанный выше объект на корневой
db.things.aggregate([
{ $match: { _id: 1, "users.role": "creator" } },
{
$addFields: {
users: {
$arrayElemAt: [
{
$filter: {
input: "$users",
cond: { $eq: ["$this.role", "creator"] }
}
},
0
]
}
}
},
{
$lookup: {
from: "Users",
localField: "users.userId",
foreignField: "_id",
as: "users"
}
},
{
$replaceRoot: {
newRoot: { $arrayElemAt: ["$users", 0] }
}
}
])