J'essaie d'apprendre à utiliser MongoDB et je suis vraiment confus comment le faire. Ce que j'ai, ce sont deux collections, une qui a un certain nombre d'utilisateurs et une autre qui a un certain nombre d'articles. Par exemple:

Utilisatrices:

{
    "_id" : ObjectId("56dba03438e1a255b97e82b6"),
    "name" : "john",
    "age" : 25
}

Articles:

{
    "_id" : ObjectId("56dba0db38e1a255b97e82b7"),
    "name" : "pencil"
}

Maintenant, ce que je veux faire dans mon application est de permettre aux utilisateurs de sélectionner un élément, mais plusieurs utilisateurs peuvent sélectionner le même élément. Je dois donc savoir quels utilisateurs ont cliqué sur quels éléments. J'ai pensé à faire cela en utilisant une autre collection qui garde la trace de l'ID utilisateur et de l'ID d'élément (un utilisateur ne peut sélectionner un élément qu'une seule fois). Est-ce la bonne approche? J'ai créé cette collection:

Useritems:

{ 
    "_id" : ObjectId("56dba0db38e1a255b97e82b7"),
    "userid" : "56db9fb038e1a255b97e82b5",
    "itemid" : "56dba03438e1a255b97e82b6"
}

Si c'est la bonne approche, je veux pouvoir cliquer sur un élément dans mon application et afficher une liste de tous les utilisateurs qui ont sélectionné cet élément. Comment puis-je faire ceci? Je suis allé jusqu'à afficher uniquement les documents de la collection useritems où le itemid = itemid sélectionné sur l'application ... mais maintenant comment afficher tous les utilisateurs de la collection d'utilisateurs en fonction de ceux de la collection useritems?

router.get('/userlist/:id', function(req, res) {  
    var db = req.db;  
    var collection = db.get('useritems');  
    collection.find({'itemid' : '_id'},{},function(e,docs){  
       res.json(docs);     
    });  
});  

Merci pour l'aide, j'ai vraiment du mal à comprendre comment cela fonctionnerait.

2
user2573690 7 mars 2016 à 03:39

4 réponses

Meilleure réponse

L'idée de créer une troisième collection est une solution qui reflète la façon dont vous résoudriez ce problème dans une base de données relationnelle. Avec MongoDB, il est souvent rentable de penser à différents modèles en fonction de la façon dont vous accédez à vos données.

Dans votre cas, je ne créerais pas une autre collection, mais je suivrais quel utilisateur a sélectionné quel élément dans le document utilisateur, dans le document article ou dans les deux documents. La façon dont vous procédez dépend de vos modèles d'accès aux données.

Ajout de l'élément sélectionné au document utilisateur

{
    "_id": ObjectId("56dba03438e1a255b97e82b6"),
    "name": "john",
    "age": 25,
    "selectedItemId": "56dba0db38e1a255b97e82b7"
}

Si vous souhaitez souvent voir l'élément que chaque utilisateur a sélectionné, il est judicieux de stocker l'élément dans le document utilisateur. Lorsque vous récupérez un utilisateur, vous n'aurez qu'à effectuer un appel supplémentaire à la collection d'éléments pour récupérer l'élément pour cet utilisateur. (Si vous décidez d'utiliser Mongoose comme mappeur objet-document (ODM), vous pouvez réaliser cet appel supplémentaire en utilisant méthode populate de Mongoose).

Ajout d'un utilisateur au document article

{
    "_id": ObjectId("56dba03438e1a255b97e82b7"),
    "name": "pencil",
    "selectedBy": [
        "56dba0db38e1a255b97e82b4",
        "56dba0db38e1a255b97e82b5",
        "56dba0db38e1a255b97e82b6"
    ],
}

Si vous souhaitez souvent voir quels utilisateurs ont sélectionné un élément donné, il est judicieux de stocker un tableau d'utilisateurs dans le document d'élément. Lorsque vous récupérez un élément, vous disposez alors des ID des utilisateurs qui ont sélectionné cet élément, que vous pouvez ensuite récupérer dans la base de données. (Encore une fois, si vous décidez d'utiliser Mongoose, vous pouvez le faire en utilisant son populate méthode).

Ajout des deux solutions

La raison pour laquelle vous préféreriez une solution à une autre est que, compte tenu de votre modèle d'accès, vous serez épargné d'itérer dans toute la collection pour obtenir les données dont vous avez besoin. Par exemple, dans le cas où vous ajoutez le tableau d'utilisateurs à un élément, si vous souhaitez rechercher l'élément sélectionné par un utilisateur donné, vous devrez parcourir tous les éléments et regarder dans le tableau des ID utilisateur jusqu'à ce que vous trouviez l'utilisateur que vous vouliez. Quelque chose de similaire se produirait si vous stockiez uniquement l'ID d'élément dans un document utilisateur et que vous deviez soudainement regarder tous les utilisateurs pour un élément donné. Si ces deux appels sont effectués souvent, cela vaut la peine d'avoir les données aux deux endroits. En effet, cela «dénormalise» vos données et vous devrez vous assurer que lorsque vous insérez, mettez à jour et supprimez les données, vous le faites aux deux endroits, mais c'est une solution beaucoup plus évolutive si vous effectuez souvent les deux types de requêtes.

Incorporation du document d'élément entier dans le document utilisateur

{
    "_id": ObjectId("56dba03438e1a255b97e82b6"),
    "name": "john",
    "age": 25,
    "selectedItem": {
        "name": "pencil"             
    }
}

Après le commentaire du PO, je vais également aborder ce scénario. C'est également une solution possible et peut être très utile pour simplifier la requête nécessaire pour accéder aux données. En interrogeant simplement le document utilisateur, vous pourrez accéder à l'élément qu'il / elle a sélectionné sans la requête supplémentaire à une collection d'éléments. La limite de cette approche est que si, pour une raison quelconque, vous souhaitez mettre à jour le nom de l'élément, par exemple "pencil" en "Pencil", vous devrez vous assurer de le mettre à jour dans tous les documents utilisateur, sinon vos données seront incohérentes. Cela devient plus compliqué lorsque vos documents intégrés sont plus complexes. Néanmoins, c'est une solution largement utilisée. Si vous mettez rarement à jour vos données, mais que vous les lisez très souvent, surtout si vous êtes plus intéressé à voir l'élément sélectionné par un utilisateur donné, cela accélère définitivement vos modèles d'accès aux données les plus fréquents.

2
Juan Carlos Farah 11 mars 2016 à 08:18

Vous pouvez ajouter un tableau dans le document d'élément qui conserve la trace des ID des utilisateurs qui ont cliqué sur cet élément. Cela suppose que l'ID est stocké dans une session active.

Docs.user_who_clicked.push (req.user._id); docs.save ()

0
Dossey Richards 7 mars 2016 à 03:21

Je ne créerais pas une collection séparée juste pour ça, sauf si vous avez une bonne raison. Ajoutez simplement un selectedBy à chaque document Item. De plus, je trouve plus simple d'utiliser simplement mes propres noms ou identifiants uniques plutôt que de chercher des choses avec les identifiants Mongo internes. Quelque chose comme ça:

var items = db.collection('items');                                                                                                                
items.updateOne({itemname:'nuts'},{$push:{selectedBy:'johns'}});                                                                                   
//...                                                                                                                                              
items.find({itemname:'nuts'}).toArray(function(err,items) {                                                                                        
  console.log(items[0].selectedBy);                                                                                                                
  db.close();
});
0
Jason Livesay 7 mars 2016 à 05:04

Vous avez raison, il vous suffit de remplir le ID utilisateur pour obtenir tous les attributs de cette collection. Je vous suggère d'utiliser (si ce n'est pas le cas) Mongoose

Avec mangouste:

UserItems
  .find({'itemid' : '_id'})
  .populate('userid')
  .then( useritems => {
     // here you have all users with their data for a specific item
     return res.json(useritems);
  });
0
DJeanCar 7 mars 2016 à 01:46