2013-08-20 1 views
0

Я внедряю социальную сеть в MongoDB, и мне нужно отслеживать последователей и следующих для каждого пользователя. Когда я ищу пользователей, я хочу отобразить список, подобный Facebook, с именем пользователя, изображением и номером последователей & Далее. Если бы я просто хотел отобразить имя пользователя и изображение (информация, которая не изменяется), это было бы легко, но мне также нужно отобразить количество последователей & Далее (что довольно регулярно меняется).Социальная сеть MongoDB Добавление последователей

Моей текущая стратегия встраивать Человек пользователя обращается в каждую пользователя Документ:

firstName: "Joe", 
lastName: "Bloggs", 
follows: [ 
{ 
    _id: ObjectId("520534b81c9aac710d000002"), 
    profilePictureUrl: "https://pipt.s3.amazonaws.com/users/xxx.jpg", 
    name: "Mark Rogers", 
}, 
{ 
    _id: ObjectId("51f26293a5c5ea4331cb786a"), 
    name: "The Palace Bar", 
    profilePictureUrl: "https://s3-eu-west-1.amazonaws.com/businesses/xxx.jpg", 
} 
] 

Возникает вопрос - Что является лучшей стратегией для отслеживания количества отслеживаемых & следующего для каждого пользователя?

Если я включаю число Следит/После в рамках внедренного документа, т.е.

follows: [ 
{ 
    _id: ObjectId("520534b81c9aac710d000002"), 
    profilePictureUrl: "https://pipt.s3.amazonaws.com/users/xxx.jpg", 
    name: "Mark Rogers", 
    **followers: 10,** 
    **following: 400** 
} 

, то каждый раз, когда пользователь следует кто-то требует несколько обновлений во всех вложенных документов.

Поскольку согласованность этих данных не очень важна (т. Е. Показать кого-то, у меня есть 10 вместо 11 последователей, это не конец света), я могу поставить в очередь это обновление. Является ли этот подход одобренным или может предложить лучший подход?

ответ

1

Вы на правильном пути. Подумайте, какой расчет выполняется больше - определить количество последователей/следующее или изменить количество последователей/следующее? Даже если вы кэшируете вывод # последователей/после вычисления, он все равно будет выполняться на один или два порядка чаще, чем изменение числа.

Также подумайте об обратном. Если вам действительно нужно отобразить количество последователей/следящих за каждым из этих пользователей, вам нужно будет делать агрегат на каждой загрузке (или кэшировать его где-то, но вы все еще делаете множество вычислений).

Вариант 1: Закрепите количество последователей/следующих во встроенном документе.
расквитаться: Может отображать статистику в O (1) время
Недостатки: Требует O (N) время, чтобы следовать/неследовать

Вариант 2: Подсчитайте число последователей/следующее на каждой странице (или кэш недействительности)
расквитаться: может последовать/неследовать в O (1) время
минусов: Требует O (N) время для отображения

Добавить в том, что подписчик/следующие статистики могут быть в конечном счете соответствует тогда отсчетам должны будет отображаться по требованию, и я думаю, что это довольно простое решение для его кеширования.

+0

Спасибо за отличную обратную связь Мейсон. Я реализовал вариант 1, посмотрите ниже. Заинтересованность услышать любые мысли :) –

0

Я пошел дальше и внедряю последователей обновления/следуя на основе той же стратегии, рекомендованной Мейсоном (Вариант 1). Вот мой код в NodeJs и Mongoose и использование модели AsyncJs Waterfall в случае, если кто-то заинтересован или имеет какие-либо мнения. Я еще не реализовал очередность, но план состоял бы в том, чтобы скомпилировать большую часть этого из очереди в очередь.

async.waterfall([ 

     function (callback) { 

      /** find & update the person we are following */ 
      Model.User 
       .findByIdAndUpdate(id,{$inc:{followers:1}},{upsert:true,select:{fullName:1,profilePictureUrl:1,address:1,following:1,followers:1}}) 
       .lean() 
       .exec(callback); 
     }, 
     function (followee, callback) { 

      /** find & update the person doing the following */ 
      var query = { 
       $inc:{following:1}, 
       $addToSet: { follows: followee} 
      } 

      Model.User 
       .findByIdAndUpdate(credentials.username,query,{upsert:true,select:{fullName:1,profilePictureUrl:1,address:1,following:1,followers:1}}) 
       .lean() 
       .exec(function(err,follower){ 
        callback(err,follower,followee); 
       }); 

     }, 
     function(follower,followee,callback){ 

      /** update the following count */ 
      Model.User 
       .update({'follows._id':follower.id},{'follows.$.following':follower.following},{upsert:true,multi:true},function(err){ 
        callback(err,followee); 
       }); 
     }, 
     function(followee,callback){ 
      /** update the followers count */ 
      Model.User 
       .update({'follows._id':followee.id},{'follows.$.followers':followee.followers},{upsert:true,multi:true},callback); 
     } 
    ], function (err) { 
     if (err) 
      next(err); 
     else { 
      res.send(HTTPStatus.OK); 
      next(); 
     } 
    }); 
+0

Убедитесь, что вы обрабатываете свои ошибки.Например, если в вашем втором обновлении произошел сбой, тогда мы получим одностороннее следование вместо обратного следования, и пользователь, которого мы придерживаемся, их номер «последователей» перестает синхронизироваться. Самое простое, вероятно, отслеживать ошибки, а затем пытаться отменить все, что вы сделали. Возможно, вам также захочется настроить фоновый процесс, который выполняется за пределами системы, чтобы все оставалось согласованным. – Mason

 Смежные вопросы

  • Нет связанных вопросов^_^