#mongodb #spring-mongodb
#mongodb #spring-mongodb
Вопрос:
Допустим, у меня есть следующая структура БД, у меня есть коллекция пользователей
"users": [
{
"_id": "4775222e-8e4f-4f84-8dba-b097291bbd39",
"surname": "Smith",
"forename": "John"
}
]
У меня есть коллекция job_requests, в которой есть ссылка на коллекцию пользователей в 1 поле, например:
"job_requests": [
{
"_id": "f4bdda3e-0e8d-4e8d-b070-7d01421f5a51",
"description": "do something",
"riskManager": {
"$ref": "users",
"$id": "4775222e-8e4f-4f84-8dba-b097291bbd39"
}
}
]
И, наконец, у меня есть коллекция заданий, в которой есть ссылка на коллекцию job_requests в 1 поле:
"jobs": [
{
"_id": "someID",
"description": "do something",
"jobRequest": {
"$ref": "job_requests",
"$id": "f4bdda3e-0e8d-4e8d-b070-7d01421f5a51"
}
}
]
Мне нужен запрос, который вернет все задания по идентификатору пользователя, что означает, что мне нужно найти все job_requests с этим пользователем, а затем все задания с этими job_requests.
Я попробовал с агрегацией mongo на MongoPlayground, и это работает, но только для mongo 4.4.1
db.jobs.aggregate([
{
"$lookup": {
"from": "job_requests",
"localField": "jobRequest.$id",
"foreignField": "_id",
"as": "jobRequest"
}
},
{
"$unwind": "$jobRequest"
},
{
"$match": {
"jobRequest.riskManager.$id": "4775222e-8e4f-4f84-8dba-b097291bbd39"
}
}
])
И дает мне правильный результат. Проблема в том, что мой сервер 4.2.8, и в этой версии это приводит к ошибке «Имена полей FieldPath могут не начинаться с ‘$'».
Как я могу сделать запрос, чтобы он не прерывался на 4.2.8? Я не могу реструктурировать данные, мне нужно иметь все эти отношения между коллекциями. Я мог бы добавить, что серверная часть поверх этого — spring data mongodb, поэтому я могу использовать эти функции для построения запроса, но я предполагаю, что это сводится к javascript для mongo QL.
Ответ №1:
Как предлагается в этом сообщении в блоге, это можно сделать с помощью оператора $objectToArray, $arrayElemAt и $ addFields.
таким образом, это становится чем-то вроде
db.jobs.aggregate([
{
"$addFields": {
"jobRequest": {
"$arrayElemAt": [
{
"$objectToArray": "$jobRequest"
},
1
]
}
}
},
{
"$addFields": {
"jobRequest": "$jobRequest.v"
}
},
{
"$lookup": {
"from": "job_requests",
"localField": "jobRequest",
"foreignField": "_id",
"as": "jobRequest"
}
},
{
"$addFields": {
"jobRequest": {
"$arrayElemAt": [
"$jobRequest",
0
]
}
}
},
{
"$unwind": "$jobRequest"
},
{
"$match": {
"jobRequest.riskManager.$id": "4775222e-8e4f-4f84-8dba-b097291bbd39"
}
}
])
Избегайте DBRef любой ценой при использовании mongo.