20 votes

MongoDB - Comment puis-je trouver tous les documents qui ne sont pas référencés par un document d'une autre collection ?

Voici donc le problème :

J'ai un document dans la collection A. Lorsqu'il est créé pour la première fois, il n'est pas référencé par d'autres documents. À un moment donné, un document de la collection B sera créé et référencera l'ObjectId d'un document de la collection A.

Quelle est la meilleure façon de trouver tous les documents de la collection A qui ne sont pas référencés par un document de la collection B ?

Je sais que MongoDB ne prend pas en charge les jointures, mais je me demande s'il existe une autre solution à ce problème que de récupérer tous les ID d'objets référencés dans la collection B et de trouver les documents de la collection A qui ne figurent pas dans cette liste, car cette solution ne serait probablement pas très évolutive.

Puis-je simplement intégrer le document de la collection A dans le document de la collection B, puis le supprimer de la collection A ? Est-ce la meilleure solution ?

Merci pour votre aide et vos commentaires.

18voto

Elad Nava Points 1619

Avec MongoDB 3.2, l'ajout de la fonction $lookup rend cela possible :

db.a.aggregate(
[
    {
        $lookup: {
            from: "b", <-- secondary collection name containing references to _id of 'a'
            localField: "_id",  <-- the _id field of the 'a' collection
            foreignField: "a_id", <-- the referencing field of the 'b' collection
            as: "references"
        }
    },
    {
        $match: {
            references: []
        }
    }
]);

La requête ci-dessus retournera tous les documents de la collection a qui n'ont pas de références dans la collection b .

Soyez prudent avec ça, cependant. Les performances peuvent devenir un problème avec les grandes collections.


5voto

Ian Mercer Points 19271

Beaucoup d'options :

1) Ajouter l'id du document B à un tableau dans le document A (une référence inverse). Vous pouvez maintenant rechercher les documents A qui n'ont pas d'éléments dans ce tableau. Problème : le tableau peut devenir trop grand pour la taille du document si vous avez beaucoup de références croisées.

2) Ajouter une collection C qui suit les références entre les A et les B. Se comporte comme une table de jointure.

3) Avoir un drapeau simple en A 'référencé'. Lorsque vous ajoutez un B, marquez tous les A qu'il référence comme étant 'référencés'. Lorsque vous supprimez un B, faites un scan de B pour tous les A qui sont référencés par lui et désélectionnez tous les A qui n'ont plus de référence. Problème : risque de désynchronisation.

4) Utiliser map reduce sur B pour créer une collection contenant les identifiants de tous les A qui sont référencés par un B. Utiliser cette collection pour marquer tous les A qui sont référencés (après les avoir tous démarqués au préalable). On peut utiliser ceci pour corriger (3) périodiquement.

5) Mettre les deux types de documents dans la même collection et utiliser map reduce pour émettre l'_id et un drapeau pour dire 'dans A' ou 'référencé par B'. Dans l'étape de réduction, recherchez tous les groupes qui ont 'dans A' mais pas 'référencé par B'.

...

0voto

McGarnagle Points 56802

Puisqu'il n'y a pas de jointures, les seules options sont celles que vous mentionnez : soit utiliser des documents intégrés, soit se résigner à utiliser des requêtes en deux parties.

Cela dépend de votre mise en œuvre, mais ajouter le type de document B au document correspondant dans A semble être la meilleure solution. De cette façon, vous pouvez récupérer les A sans B en utilisant une requête simple ( opérateur $exists )...

A.find( { B: { $exists: false } })

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X