Je travaille sur la gestion des versions, nous avons des documents basés sur les UUIDs
et les jobUuids
, et les jobUuids
sont les documents associés à l'utilisateur actuellement en activité. J'ai quelques requêtes agrégées sur ces collections que je dois mettre à jour en fonction des UUID du travail,
Les résultats récupérés par la requête agrégée doivent être tels que,
jobUuid
utilisateur actuel n'existe pas alors le document maître avec jobUuid: "default"
sera renvoyé (le document sans jobUuid), J'ai un $match
utilisé pour obtenir ces documents en fonction de certaines conditions, à partir de ces documents, je dois filtrer les documents en fonction des conditions ci-dessus, et un exemple est montré ci-dessous,
Les données ressemblent à ceci:
[ { "uuid": "5cdb5a10-4f9b-4886-98c1-31d9889dd943", "jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12", "name": "adam" }, { "uuid": "b745baff-312b-4d53-9438-ae28358539dc", "jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12", "name": "eve" }, { "uuid": "26cba689-7eb6-4a9e-a04e-24ede0309e50", "name": "john", "jobUuid": "default", } ]
Les résultats pour "jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12"
doivent être:
[ { "uuid": "5cdb5a10-4f9b-4886-98c1-31d9889dd943", "name": "adam", "jobUuid": "default", }, { "uuid": "5cdb5a10-4f9b-4886-98c1-31d9889dd943", "jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12", "name": "adam" }, { "uuid": "b745baff-312b-4d53-9438-ae28358539dc", "name": "eve", "jobUuid": "default", }, { "uuid": "b745baff-312b-4d53-9438-ae28358539dc", "jobUuid": "d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12", "name": "eve" }, { "uuid": "26cba689-7eb6-4a9e-a04e-24ede0309e50", "name": "john", "jobUuid": "default", } ]
Sur la base des conditions mentionnées ci-dessus, est-il possible de filtrer le document dans la requête agrégée pour extraire le document d'un uuid de travail spécifique?
Edit 1: J'ai eu la solution suivante, qui fonctionne bien, je veux une meilleure solution, éliminant toutes ces conditions imbriquées.
Edit 2: Mise à jour des données avec les UUID réels et je viens d'inclure uniquement le name
dans un autre champ, nous avons n
nombre de champs qui ne sont pas pertinents à inclure ici mais nécessaires à la fin.
3 Réponses :
J'ai pu résoudre ce problème avec la requête agrégée suivante,
Nous jobUuid
abord les résultats correspondant uniquement au jobUuid
fourni par l'utilisateur ou au "default"
dans la section match.
Ensuite, les résultats sont regroupés en fonction de l'uuid, en utilisant une phase de groupes et nous comptons également les résultats.
En utilisant les conditions de replaceRoot
nous replaceRoot
abord la longueur du document groupé,
Si la longueur du document groupé est supérieure ou égale à 2, nous filtrons le document qui correspond au jobUuid fourni.
S'il est inférieur ou égal à 1, nous vérifions s'il correspond au jobUuid default
et le retournons.
La requête est ci-dessous:
[ { $match: { $or: [{ jobUuid:1 },{ jobUuid: 'default'}] } }, { $group: { _id: '$uuid', count: { $sum: 1 }, docs: { $push: '$$ROOT' } } }, { $replaceRoot: { newRoot: { $cond: { if: { $gte: [ '$count', 2 ] }, then: { $arrayElemAt: [ { $filter: { input: '$docs', as: 'item', cond: { $ne: [ '$$item.jobUuid', 'default' ] } } }, 0 ] }, else: { $arrayElemAt: [ { $filter: { input: '$docs', as: 'item', cond: { $eq: [ '$$item.jobUuid', 'default' ] } } }, 0 ] } } } } } ]
Voici ce que je ferais:
Testé sur: https://mongoplayground.net/p/e76cVJf0F3o
[{ "$match": { "jobUuid": { "$in": [ "1", "default" ] } } }, { "$group": { "_id": "$uuid", "name": { "$first": "$name" }, "jobUuids": { "$addToSet": { "$cond": { "if": { "$ne": [ "$jobUuid", "default" ] }, "then": "$jobUuid", "else": "$$REMOVE" } } } } }, { "$project": { "_id": 0, "uuid": "$_id", "name": 1, "jobUuid": { "$ifNull": [{ "$arrayElemAt": [ "$jobUuids", 0 ] }, "default" ] } } }]
Merci pour votre solution, ici je n'ai pas mentionné que j'ai n
nombres de champs dans la réponse. Le problème avec cette solution est que je dois inclure tous les champs dans la $group
ce qui est vraiment gênant.
Mise à jour basée sur un commentaire:
mais les UUID sont des chaînes alphanumériques, comme indiqué ci-dessus, cela a-t-il un effet sur ces tri, et comme nous n'utilisons pas de conditions pour obtenir les résultats, je crains que cela ne pose des problèmes.
Vous pouvez utiliser un champ supplémentaire pour faire correspondre l'ordre de tri afin qu'il soit du même ordre que les valeurs de l'expression in. Assurez-vous de fournir les valeurs par défaut comme dernière valeur.
[ {"$match":{"jobUuid":{"$in":[1,"default"]}}}, {"$sort":{"uuid":1, "jobUuid":1}}, { "$group": { "_id": "$uuid", "doc":{"$first":"$$ROOT"} } }, {"$replaceRoot":{"newRoot":"$doc"}} ]
exemple ici - https://mongoplayground.net/p/wXiE9i18qxf
Original
Vous pouvez utiliser la requête ci-dessous. La requête choisira le document non par défaut s'il existe pour uuid ou bien choisir le document par défaut comme seul document.
[ {"$match":{"jobUuid":{"$in":["d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12","default"]}}}, {"$addFields":{ "order":{"$indexOfArray":[["d275781f-ed7f-4ce4-8f7e-a82e0e9c8f12","default"], "$jobUuid"]}}}, {"$sort":{"uuid":1, "order":1}}, { "$group": { "_id": "$uuid", "doc":{"$first":"$$ROOT"} } }, {"$project":{"doc.order":0}}, {"$replaceRoot":{"newRoot":"$doc"}} ]
exemple ici - https://mongoplayground.net/p/KrL-1s8WCpw
Merci pour votre solution, ici nous trions en fonction de l'uuid et du jobUuid, auparavant c'était des entiers, mais les UUID sont des chaînes alphanumériques, comme indiqué ci-dessus, cela a-t-il un effet sur ces tri, et puisque nous n'utilisons pas de conditions pour obtenir les résultats, je crains que cela ne cause des problèmes.
Np - Réponse mise à jour pour inclure un champ supplémentaire pour correspondre à l'ordre de tri afin qu'il soit du même ordre que les valeurs de l'expression in.
Je suis désolé, la deuxième étape de la réponse mise à jour n'a pas de sens pour moi, j'ai l'impression que nous pouvons simplement la remplacer par 0 ou 1 en fonction de la façon dont nous fournissons le tableau uuid du travail. Avons-nous vraiment besoin de cette étape?
Pas de soucis - sans savoir quel document correspond à quel jobUuid vous ne pourrez pas attribuer 1 ou 0, non? C'est une vérification par rapport aux valeurs d'entrée pour affecter l'ordre - peut-être que vous pouvez le simplifier en utilisant l'opérateur cond car il n'y a que deux entrées. Si jobUUid est défini par défaut, attribuez 1 sinon 0
Je pense que l'opérateur conditionnel est le bon choix car il n'a pas besoin de dépendre de l'expression d'entrée pour attribuer l'ordre. La deuxième étape peut être {"$addFields":{ "order":{"$cond":[{"$eq":["default","$jobUuid"]}, 1, 0]}}}
place. Je crois que c'est ce à quoi vous faites référence.
Cela semble bon, j'attendrai un certain temps pour voir d'autres solutions avant d'accepter, merci pour votre temps!