MongoDB: поиск ассиметричных записей
-
Дано: коллекция account с вложенными объектами коллекции contact.
Проблема: в коллекции contact есть объекты, которые не содержатся у обьектов account
Задача: вывести списком contact._id, которых нет у обьектов коллекции accountДокумент коллекции contact
[ { **"_id": "47d",** "_lastUpdatedAt": 1603484561997, **"accounts"**: [ { **"accountId": "7eb",** "accountNumber": "765", "status": 2, "isPrimaryOwner": true, "alertIds": [] } ], "customFieldValues": [], "isActive": true, "notes": [], "primaryAccountId": "7eb", "status": 3, "type": 1 } ]
Документ коллекции account
[ { **"_id": "7eb",** "_lastUpdatedAt": 1603484561785, "accountId": "7eb", "accountNumber": "765", **"owners"**: [ { **"contactId": "47d"**, "type": 1, "sourceOf": "" }, "contacts": { "phones": [ { "phoneId": "016", "type": 4, "isAccountDriven": true }, { "phoneId": "337", "type": 4, "isAccountDriven": true } ], "emails": [ { "emailId": "c1a", "type": 3, "isAccountDriven": true } ], "links": [], "addresses": [ { "addressId": "9e0", "type": 3, "isAccountDriven": true } ], "primaryPhoneId": "016", "primaryEmailId": "c1a", "primaryAddressId": "9e0" } } ], "status": 2, } ]
Составленный запрос в Mongo:
db.contact.aggregate( { $lookup: { from: "account", let: { "contactId": "$_id" }, pipeline: [ { $match: { $expr: {$ne:["$contact._id", "$$contactId"] } } }, { $group: { _id: "$_id", totalCount: { $sum: 1 } } }, { $project: { "_id": 1, "totalCount": 1 } } ], as: "contacts" }}, { $project: { _id: 1, "totalcontacts" : {$size:"$contacts"} } } )
Запрос выдает ошибку:
com.mongodb.MongoCommandException: Command failed with error 16945 (Location16945): 'Exceeded memory limit for $group, but didn't allow external sort. Pass allowDiskUse:true to opt in.' on server хххххх The full response is {"operationTime": {"$timestamp": {"t": 1633731680, "i": 8}}, "ok": 0.0, "errmsg": "Exceeded memory limit for $group, but didn't allow external sort. Pass allowDiskUse:true to opt in.", "code": 16945, "codeName": "Location16945", "$clusterTime": {"clusterTime": {"$timestamp": {"t": 1633731680, "i": 8}}, "signature": {"hash": {"$binary": {"base64": "/Sd6PcJ9zyM=", "subType": "00"}}, "keyId": 091949063}}}
Была попытка встроить unwind или allowDiskUse, но не понятно на каком этапе это необходимо делать.
-
Пользователь @admin написал в MongoDB: поиск ассиметричных записей:
[{
$skip: 100
}, {
$limit: 100
}, {
$lookup: { ...Спасибо большое за помощь!
Запрос обрабатывает записи группами. -
Это сообщение удалено! -
Если записей очень много, то Вы можете обрабатывать их группами по 100 записей за раз, например. Для этого можно использовать $skip и $limit.
[{ $skip: 100 }, { $limit: 100 }, { $lookup: { ...
-
Я думаю нужно идти по такому пути:
- К коллекции "contact" прицепляем данные из "account" через $lookup.
- Ищем те элементы, у которых массив прицепленных данных пустой.
- Нужен массив ID? Группируем и убираем лишнее через $project.
Пример (не проверял):
[{ $lookup: { from: 'account', localField: '_id', foreignField: 'owners.contactId', as: 'accounts' } }, { $match: { "accounts": [] } }, { $group: { _id: null, ids: { '$push': '$_id' } } }, { $project: { '_id': 0 } }]