2017-10-15 75 views
5

Lemme poświęć czas, aby wyjaśnić, co się dzieje od początku do końca.zapełnianie następujących użytkowników mongoose

Preambuła:

Użytkownik następuje 10 innych osób. Gdy użytkownik A się zaloguje, zostanie wyświetlona X liczba postów z każdej z 10 osób.

Nie wiem, czy to słuszne, i docenię lepszy sposób robienia tego. Jednak chcę spróbować, i to nie działa.

Obserwuj model:

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); 

Karta model

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); 

logika Obserwuj

Gdy użytkownik A następująco użytkownik B, zrobić dwie rzeczy:

  • Pchnąć user_id B użytkownikowi dokument na polu 'po' (A obserwuje B)
  • push user_id od A do użytkownika dokument B na 'zwolenników' Field (B następuje)

    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' 
        }) 
    }) 
    

    })

Rzeczywista DB wartości

> 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") 
    ] 
} 
> 

Z powyższych wyników bazy danych, to jest moje zapytanie:

Zapytanie

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 
      }) 
     }) 
}); 

Z powyższego zapytania, ze moja mała zrozumienie Mongoose zapełnić, spodziewam się dostać karty z każdego Użytkownicy w tablicy following.

Moje zrozumienie i oczekiwania mogą być błędne, jednak z takim zakończeniem, czy to zaludnione podejście jest w porządku? Czy próbuję rozwiązać zadanie agregacji z populacją?

UPDATE:

Dzięki za odpowiedź. Coraz bliżej, ale mimo to tablica followingCards nie zawiera żadnych wyników.Oto treść mojego obecnego Follow modelu

> 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") 
    ] 
} 
> 

Oto lista obecnej zawartości mam z Card Model:

> 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 
} 

Z zapełnić Wirtualnej przykład od Ciebie (@Veeram), oto odpowiedź Otrzymuję:

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

Tablica followingCards jest pusta.

Korzystanie zapytania $lookup z drugiej strony po prostu zwraca []

jestem prawdopodobnie brakuje czegoś?

+0

Edytuj swoje pytanie ze swoich schematów. – Mikey

+0

@JohnnyHK ok. zrobi. – Rexford

+0

zapełnianie działa tylko wtedy, gdy przed zapisaniem pchnąłeś ref do Follow.following! –

Odpowiedz

2

Możesz użyć wirtualnej populacji lub $lookup operator w potoku agregacji.

Korzystanie z wirtualnej zapełnić

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)); 
}); 

Korzystanie $lookup agregacji

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

Dzięki za odpowiedź. Próbowałem twoich podejść. Tablica 'followingCards' jest wówczas częścią obiektu odpowiedzi, jednak tablica zawiera pustą listę. Aktualne wartości aktualnych wartości w DB znajdują się teraz. – Rexford

+0

Np. Czy możesz dodać 'mongoose.set ('debug', true);' u góry pliku, aby zobaczyć jakie zapytania są wysyłane do mongodb? Btw Naprawiłem odnośnik, aby zawierał poprawną nazwę kolekcji 'cards'. Czy możesz również spróbować wyszukać agregację bez etapu dopasowań, aby sprawdzić, czy działa, a następnie możesz ją odłożyć? – Veeram

+0

Wartości pól tablicy "poniższa" w kolekcjach 'follow' nie ma pasującego' createdById' w kolekcji 'cards'. Spróbuj użyć pola "followers" zamiast danych, które podasz i możesz odpowiednio dostosować odpowiedź. – 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); 

Aby pokazać, jak jest wykorzystywany Populate najpierw utworzyć obiekt osoby,

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

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

Następnie, po dokonaniu zapytanie, można wypełnić odniesienia, takie jak ten:

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

// działa tylko wtedy, gdy pchnęliśmy odwołania do osoby.eventsAttended