2017-10-15 4 views
5

Lemme prend le temps d'expliquer ce qui se passe du début à la fin.peupler les utilisateurs suivants mongoose

Préambule:

A un utilisateur suit 10 autres personnes. Lorsque l'utilisateur A se connecte, un nombre X de messages de chacune des 10 personnes sont affichés.

Je ne sais pas si c'est la bonne chose à faire, et j'apprécierai une meilleure façon de le faire. Cependant, je veux essayer et ça ne marche pas.

Suivre Modèle:

let mongoose = require('mongoose'); 
let Schema = mongoose.Schema; 

let FollowSchema = new Schema({ 
    user: { 
    type: Schema.Types.ObjectId, 
    ref: 'User' 
    }, 
    followers: [{ 
    type: Schema.Types.ObjectId, 
    ref: 'Card' 
    }], 
    following: [{ 
    type: Schema.Types.ObjectId, 
    ref: 'Card' 
    }] 
}); 

module.exports = mongoose.model('Follow', FollowSchema); 

Modèle Carte

let mongoose = require('mongoose'); 
let Schema = mongoose.Schema; 

let CardSchema = new Schema({ 
    title: String, 
    content: String, 
    createdById: { 
    type: Schema.Types.ObjectId, 
    ref: 'User' 
    }, 
    createdBy: { 
    type: String 
    } 
}); 

module.exports = mongoose.model('Card', CardSchema); 

Suivre la logique

Lorsque l'utilisateur A fait suite à l'utilisateur B, faire deux choses:

  • Appuyez sur le user_id de B à l'utilisateur d'un document sur le champ 'suivant' (A suit B)
  • poussoir user_id de A à l'utilisateur B document sur 'suiveurs' champ (B est suivie par A)

    router.post('/follow', utils.loginRequired, function(req, res) { 
    const user_id = req.user._id; 
    const follow = req.body.follow_id; 
    
    let bulk = Follow.collection.initializeUnorderedBulkOp(); 
    
    bulk.find({ 'user': Types.ObjectId(user_id) }).upsert().updateOne({ 
        $addToSet: { 
         following: Types.ObjectId(follow) 
        } 
    }); 
    
    bulk.find({ 'user': Types.ObjectId(follow) }).upsert().updateOne({ 
        $addToSet: { 
         followers: Types.ObjectId(user_id) 
        } 
    }) 
    
    bulk.execute(function(err, doc) { 
        if (err) { 
         return res.json({ 
          'state': false, 
          'msg': err 
         }) 
        } 
        res.json({ 
         'state': true, 
         'msg': 'Followed' 
        }) 
    }) 
    

    })

valeurs réelles DB

> db.follows.find().pretty() 
{ 
    "_id" : ObjectId("59e3e27dace1f14e0a70862d"), 
    "user" : ObjectId("59e2194177cae833894c9956"), 
    "following" : [ 
     ObjectId("59e3e618ace1f14e0a708713") 
    ] 
} 
{ 
    "_id" : ObjectId("59e3e27dace1f14e0a70862e"), 
    "user" : ObjectId("59e13b2dca5652efc4ca2cf5"), 
    "followers" : [ 
     ObjectId("59e2194177cae833894c9956"), 
     ObjectId("59e13b2d27cfed535928c0e7"), 
     ObjectId("59e3e617149f0a3f1281e849") 
    ] 
} 
{ 
    "_id" : ObjectId("59e3e71face1f14e0a708770"), 
    "user" : ObjectId("59e13b2d27cfed535928c0e7"), 
    "following" : [ 
     ObjectId("59e3e618ace1f14e0a708713"), 
     ObjectId("59e13b2dca5652efc4ca2cf5"), 
     ObjectId("59e21942ca5652efc4ca30ab") 
    ] 
} 
{ 
    "_id" : ObjectId("59e3e71face1f14e0a708771"), 
    "user" : ObjectId("59e3e618ace1f14e0a708713"), 
    "followers" : [ 
     ObjectId("59e13b2d27cfed535928c0e7"), 
     ObjectId("59e2194177cae833894c9956") 
    ] 
} 
{ 
    "_id" : ObjectId("59e3e72bace1f14e0a708779"), 
    "user" : ObjectId("59e21942ca5652efc4ca30ab"), 
    "followers" : [ 
     ObjectId("59e13b2d27cfed535928c0e7"), 
     ObjectId("59e2194177cae833894c9956"), 
     ObjectId("59e3e617149f0a3f1281e849") 
    ] 
} 
{ 
    "_id" : ObjectId("59f0eef155ee5a5897e1a66d"), 
    "user" : ObjectId("59e3e617149f0a3f1281e849"), 
    "following" : [ 
     ObjectId("59e21942ca5652efc4ca30ab"), 
     ObjectId("59e13b2dca5652efc4ca2cf5") 
    ] 
} 
> 

Avec les résultats de la base de données ci-dessus, ceci est ma requête:

Recherche

router.get('/follow/list', utils.loginRequired, function(req, res) { 
    const user_id = req.user._id; 

    Follow.findOne({ 'user': Types.ObjectId(user_id) }) 
     .populate('following') 
     .exec(function(err, doc) { 
      if (err) { 
       return res.json({ 
        'state': false, 
        'msg': err 
       }) 
      }; 

      console.log(doc.username); 

      res.json({ 
       'state': true, 
       'msg': 'Follow list', 
       'doc': doc 
      }) 
     }) 
}); 

Avec la requête ci-dessus, de ma petite compréhension de mangouste remplir, je me attends à obtenir des cartes de chacun des Utilisateurs dans la baie following.

Ma compréhension et mes attentes pourraient être fausses, mais avec une telle finalité, est-ce que cette approche peuplée est acceptable? Ou est-ce que j'essaie de résoudre une tâche d'agrégation avec la population?

MISE À JOUR:

Merci pour la réponse. Obtenir tout près, mais encore, le tableau followingCards ne contient aucun résultat.Voici le contenu de mon modèle actuel Follow:

> db.follows.find().pretty() 
{ 
    "_id" : ObjectId("59f24c0555ee5a5897e1b23d"), 
    "user" : ObjectId("59f24bda1d048d1edad4bda8"), 
    "following" : [ 
     ObjectId("59f24b3a55ee5a5897e1b1ec"), 
     ObjectId("59f24bda55ee5a5897e1b22c") 
    ] 
} 
{ 
    "_id" : ObjectId("59f24c0555ee5a5897e1b23e"), 
    "user" : ObjectId("59f24b3a55ee5a5897e1b1ec"), 
    "followers" : [ 
     ObjectId("59f24bda1d048d1edad4bda8") 
    ] 
} 
{ 
    "_id" : ObjectId("59f24c8855ee5a5897e1b292"), 
    "user" : ObjectId("59f24bda55ee5a5897e1b22c"), 
    "followers" : [ 
     ObjectId("59f24bda1d048d1edad4bda8") 
    ] 
} 
> 

Voici tout le contenu actuel que j'ai de Card Modèle:

> db.cards.find().pretty() 
{ 
    "_id" : ObjectId("59f24bc01d048d1edad4bda6"), 
    "title" : "A day or two with Hubtel's HTTP API", 
    "content" : "a day or two", 
    "external" : "", 
    "slug" : "a-day-or-two-with-hubtels-http-api-df77056d", 
    "createdBy" : "seanmavley", 
    "createdById" : ObjectId("59f24b391d048d1edad4bda5"), 
    "createdAt" : ISODate("2017-10-26T20:55:28.293Z"), 
    "__v" : 0 
} 
{ 
    "_id" : ObjectId("59f24c5f1d048d1edad4bda9"), 
    "title" : "US couple stole goods worth $1.2m from Amazon", 
    "content" : "for what", 
    "external" : "https://bbc.com", 
    "slug" : "us-couple-stole-goods-worth-dollar12m-from-amazon-49b0a524", 
    "createdBy" : "nkansahrexford", 
    "createdById" : ObjectId("59f24bda1d048d1edad4bda8"), 
    "createdAt" : ISODate("2017-10-26T20:58:07.793Z"), 
    "__v" : 0 
} 

Avec le Populate exemple virtuel de la vôtre (@Veeram), voici la réponse Je reçois:

{"state":true,"msg":"Follow list","doc":{"_id":"59f24c0555ee5a5897e1b23d","user":"59f24bda1d048d1edad4bda8","following":["59f24b3a55ee5a5897e1b1ec","59f24bda55ee5a5897e1b22c"],"followers":[],"id":"59f24c0555ee5a5897e1b23d","followingCards":[]}} 

Le tableau followingCards est vide.

Utilisation de la requête $lookup d'autre part retourne simplement []

Il me manque probablement quelque chose?

+0

Modifier votre question avec vos schémas. – Mikey

+0

@JohnnyHK ok. ça ira. – Rexford

+0

peupler ne fonctionne que si vous avez poussé refs à Follow.following avant de sauvegarder! –

Répondre

2

Vous pouvez utiliser soit le remplissage virtuel ou $lookup opérateur dans le pipeline d'agrégation.

En utilisant Virtual Populate

FollowSchema.virtual('followingCards', { 
    ref: 'Card', 
    localField: 'following', 
    foreignField: 'createdById' 
}); 

Follow.findOne({ 
    'user': Types.ObjectId(user_id) }) 
    .populate('followingCards') 
    .exec(function(err, doc) {  
     console.log(JSON.stringify(doc)); 
}); 

En utilisant l'agrégation $lookup

Follow.aggregate([ 
    { 
    "$match": { 
     "user": Types.ObjectId(user_id) 
    } 
    }, 
    { 
    "$lookup": { 
     "from": "cards", 
     "localField": "following", 
     "foreignField": "createdById", 
     "as": "followingCards" 
    } 
    } 
]).exec(function (err, doc) { 
    console.log(JSON.stringify(doc)); 
}) 
+0

Merci pour la réponse. J'ai essayé vos approches. Le tableau 'followingCards' fait alors partie de l'objet de réponse, cependant le tableau contient une liste vide. S'il vous plaît voir la question mise à jour pour les valeurs réelles dans la base de données actuellement. – Rexford

+0

Np. Pouvez-vous ajouter le 'mongoose.set ('debug', true);' en haut du fichier pour voir quelles requêtes sont envoyées à mongodb? Btw J'ai corrigé la recherche pour inclure le nom de collection correct 'cards'. Pouvez-vous également essayer l'agrégation de recherche sans l'étape de correspondance pour vérifier si cela fonctionne et ensuite vous pouvez le remettre? – Veeram

+0

Les valeurs de champ de tableau 'following' dans les collections' follows' n'ont pas de 'createdById' correspondant dans la collection' cards'. Essayez plutôt d'utiliser le champ 'followers' pour les données que vous avez fournies et vous pouvez ajuster la réponse de manière appropriée. – Veeram

0
var mongoose = require('mongoose'), Schema = mongoose.Schema 

var eventSchema = Schema({ 
title  : String, 
location : String, 
startDate : Date, 
endDate : Date 
}); 

var personSchema = Schema({ 
firstname: String, 
lastname: String, 
email: String, 
dob: Date, 
city: String, 
eventsAttended: [{ type: Schema.Types.ObjectId, ref: 'Event' }] 
}); 

var Event = mongoose.model('Event', eventSchema); 
var Person = mongoose.model('Person', personSchema); 

Pour montrer comment Populate est utilisé, d'abord créer un objet personne,

aaron = new Person({firstname: 'Aaron'}) and an event object, 
    event1 = new Event({title: 'Hackathon', location: 'foo'}): 

    aaron.eventsAttended.push(event1); 
    aaron.save(callback); 

Ensuite, lorsque vous faites votre requête, vous pouvez remplir des références comme celui-ci:

Person 
.findOne({ firstname: 'Aaron' }) 
.populate('eventsAttended') .exec(function(err, person) { 
if (err) return handleError(err); 
console.log(person); 
}); 

// ne fonctionne que si nous avons poussé refs à person.eventsAttended