#mongodb #mongodb-query #aggregation-framework
#mongodb #mongodb-запрос #агрегация-фреймворк
Вопрос:
Вот пример моих данных :
{
"_id": ObjectId("5fa7d0e31abef4382b15efd0"),
"users":
[
{
"_id": ObjectId("5fa667194f22083924eeca9e"),
"messageId": ObjectId("5fa7d15a1abef4382b15efd2")
},
{
"_id": ObjectId("5fa673a50af228412b0ccf2b"),
"messageId": ObjectId("5fa7d15a1abef4382b15efd1")
}
],
"messages":
[
{
"_id": ObjectId("5fa7d0e31abef4382b15efcf"),
"message": "Hi!",
"userId": ObjectId("5fa667194f22083924eeca9e")
},
{
"_id": ObjectId("5fa7d15a1abef4382b15efd1"),
"message": "Hello!",
"userId": ObjectId("5fa673a50af228412b0ccf2b")
},
{
"_id": ObjectId("5fa7d15a1abef4382b15efd2"),
"message": "How are you?",
"userId": ObjectId("5fa667194f22083924eeca9e")
}
]
}
Я пытаюсь получить позицию сообщения в массиве «сообщения», определяемую идентификатором MessageId, расположенным в массиве «пользователи».
Вот что я попробовал :
db.chat.find({ 'users._id': ObjectId("5fa667194f22083924eeca9e") },
{ 'users': 1,
'index':
{
'$indexOfArray':
[
'$messages._id',
'$users.0.toRead'
]
},
'messages.$': 1
})
Я знаю, что это сработает, если я использую :
db.chat.find({ 'users._id': ObjectId("5fa667194f22083924eeca9e") },
{ 'users': 1,
'index':
{
'$indexOfArray':
[
'$messages._id',
ObjectId("5fa7d15a1abef4382b15efd2")
]
},
'messages.$': 1
})
Но я не могу угадать идентификатор сообщения перед отправкой запроса, и я хотел бы сделать только один запрос и никаких массовых запросов. Возможно ли это сделать? Я хотел бы сделать этот индекс для обоих пользователей. Должен ли я скопировать $indexToArray дважды или есть другой способ?
Ответ №1:
Используя структуру агрегации, действительно возможно достичь желаемого результата, поскольку вы можете использовать операторы $map
для сопоставления массива users и включения нового индексного поля с $mergeObjects
оператором. Вы все равно можете использовать $indexOfArray
оператор для получения позиции идентификатора сообщения. Конечно, вам потребуется $addFields
этап конвейера для проецирования этого вновь отображенного users
поля и другого свойства документа messages
.
Следующий конвейер демонстрирует описанную выше операцию:
db.chat.aggregate([
{ '$match': { 'users._id': ObjectId("5fa667194f22083924eeca9e") } },
{ '$addFields': {
'users': {
'$map': {
'input': '$users',
'as': 'u',
'in': {
'$mergeObjects': [
'$$u',
{ 'index': {
'$indexOfArray': ['$messages._id', '$$u.messageId']
} }
]
}
}
}
} }
])